diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml new file mode 100644 index 000000000..e282e3891 --- /dev/null +++ b/.github/workflows/cmake.yml @@ -0,0 +1,38 @@ +name: CMake + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +env: + # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) + BUILD_TYPE: Release + +jobs: + build: + # The CMake configure and build commands are platform agnostic and should work equally + # well on Windows or Mac. You can convert this to a matrix build if you need + # cross-platform coverage. + # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Configure CMake + # Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make. + # See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + - name: Build + # Build your program with the given configuration + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + + - name: Test + working-directory: ${{github.workspace}}/build + # Execute tests defined by the CMake configuration. + # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail + run: ctest -C ${{env.BUILD_TYPE}} + diff --git a/.github/workflows/greetings.yml b/.github/workflows/greetings.yml new file mode 100644 index 000000000..ee1cb1167 --- /dev/null +++ b/.github/workflows/greetings.yml @@ -0,0 +1,16 @@ +name: Greetings + +on: [pull_request, issues] + +jobs: + greeting: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/first-interaction@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + issue-message: 'Message that will be displayed on users first issue' + pr-message: 'Message that will be displayed on users first pull request' diff --git a/BUILD.md b/BUILD.md index 903c29a64..e45a3ae6c 100644 --- a/BUILD.md +++ b/BUILD.md @@ -33,6 +33,22 @@ yum groupinstall "Development Tools" yum -y install cmake # install more required libraries yum -y install libpcap-devel boost-devel boost-static + +# build and install libzmq +wget https://github.com/zeromq/libzmq/archive/v4.3.2.zip +unzip v4.3.2.zip +cd /path/to/unziped/dir +mkdir build && cd build +cmake .. +sudo make -j4 install + +# build and install cppzmq +wget https://github.com/zeromq/cppzmq/archive/v4.6.0.zip +unzip v4.6.0.zip +cd /path/to/unziped/dir +mkdir build && cd build +cmake -DCPPZMQ_BUILD_TESTS=OFF .. +sudo make -j4 install ``` 2. Clone or download the project. @@ -63,6 +79,22 @@ apt-get -y install build-essential apt-get -y install cmake # install more required libraries apt-get -y install libpcap-dev libboost-all-dev + +# build and install libzmq +wget https://github.com/zeromq/libzmq/archive/v4.3.2.zip +unzip v4.3.2.zip +cd /path/to/unziped/dir +mkdir build && cd build +cmake .. +sudo make -j4 install + +# build and install cppzmq +wget https://github.com/zeromq/cppzmq/archive/v4.6.0.zip +unzip v4.6.0.zip +cd /path/to/unziped/dir +mkdir build && cd build +cmake -DCPPZMQ_BUILD_TESTS=OFF .. +sudo make -j4 install ``` 2. Clone or download the project. @@ -98,6 +130,22 @@ tar --bzip2 -xf boost_1_54_0.tar.bz2 cd boost_1_54_0/ ./bootstrap.sh ./b2 install stage + +# build and install libzmq +wget https://github.com/zeromq/libzmq/archive/v4.3.2.zip +unzip v4.3.2.zip +cd /path/to/unziped/dir +mkdir build && cd build +cmake .. +sudo make -j4 install + +# build and install cppzmq +wget https://github.com/zeromq/cppzmq/archive/v4.6.0.zip +unzip v4.6.0.zip +cd /path/to/unziped/dir +mkdir build && cd build +cmake -DCPPZMQ_BUILD_TESTS=OFF .. +sudo make -j4 install ``` 2. Clone or download the project. @@ -129,15 +177,33 @@ make install ls /usr/local/lib/libpcap* ``` -2. *Recommended*: install [brew](https://brew.sh/) for easier package management. - +3. *Recommended*: install [brew](https://brew.sh/) for easier package management. ```shell # install boost brew install boost ``` -2. Clone or download the project. -3. Build the project. +4. build and install libzmq and cppzmq +```shell +# build and install libzmq +wget https://github.com/zeromq/libzmq/archive/v4.3.2.zip +unzip v4.3.2.zip +cd /path/to/unziped/dir +mkdir build && cd build +cmake .. +sudo make -j4 install + +# build and install cppzmq +wget https://github.com/zeromq/cppzmq/archive/v4.6.0.zip +unzip v4.6.0.zip +cd /path/to/unziped/dir +mkdir build && cd build +cmake -DCPPZMQ_BUILD_TESTS=OFF .. +sudo make -j4 install +``` +5. Clone or download the project. + +6. Build the project. ```shell cd /path/to/packet-agent @@ -145,7 +211,7 @@ mkdir build && cd build cmake .. && make ``` -4. Ensure the build is successful. The *bin* folder should contain four binary files. +7. Ensure the build is successful. The *bin* folder should contain four binary files. ```shell ls ../bin diff --git a/CHANGES.md b/CHANGES.md index a31c71cb0..72f3adce2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,33 @@ The list of the most significant changes made in Netis Packet Agent over time. +## Netis Packet Agent 0.5.2 +### Features +* Supprot vlan packets + +## Netis Packet Agent 0.5.1 +### Features +* Supprot packet forword by vxlan + +## Netis Packet Agent 0.5.0 + +### Features +* Support GRE direction in key. + + +## Netis Packet Agent 0.3.6 + +### Features +* Support agent control plane for agent daemon over zeromq. + + +## Netis Packet Agent 0.3.5 + +### Features +* Support option check for '--nofilter' option invalid usage. In version 0.3.5 or later, pktminerg will exit directly in the following cases: + - if you enable '--nofilter' option without specifying gre bind device(-B) in online mode. + - if you enable '--nofilter' option and gre bind device(-B) is same as packet captured interface(-i) in online mode. + ## Netis Packet Agent 0.3.4 ### Features diff --git a/CMakeLists.txt b/CMakeLists.txt index f8d301975..b1f82b529 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,16 +6,16 @@ option(PROJECT_WITH_PROF "Enable profiling and coverage report analysis" OFF) message("\${PROJECT_WITH_PROF}: ${PROJECT_WITH_PROF}") # cmake cxx flags if (${PROJECT_WITH_PROF}) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -fprofile-arcs -ftest-coverage") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pthread -lrt -fprofile-arcs -ftest-coverage") set(LINK_FLAGS "${LINK_FLAGS} -fprofile-arcs") else () - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pthread -lrt") endif () # set PKTMINERG_MAJOR_VERSION, PKTMINERG_MINOR_VERSION, etc. set(PKTMINERG_MAJOR_VERSION "0") -set(PKTMINERG_MINOR_VERSION "3") -set(PKTMINERG_PATCH_VERSION "4") +set(PKTMINERG_MINOR_VERSION "5") +set(PKTMINERG_PATCH_VERSION "1") set(PKTMINERG_VERSION_STRING "${PKTMINERG_MAJOR_VERSION}.${PKTMINERG_MINOR_VERSION}.${PKTMINERG_PATCH_VERSION}") if(WIN32) @@ -89,6 +89,8 @@ if(UNIX) set(Boost_USE_STATIC_LIBS ON) find_package(Boost 1.41.0 REQUIRED COMPONENTS program_options system filesystem) + find_package(cppzmq) + message("Boost_INCLUDE_DIRS: " ${Boost_INCLUDE_DIRS}) message("Boost_LIBRARY_DIRS: " ${Boost_LIBRARY_DIRS}) # include dir @@ -201,17 +203,37 @@ set(SOURCE_FILES_GREDUMP ${SOURCE_FILES_PCAP} ) +set(SOURCE_FILES_VXLANDUMP + ${PROJECT_SOURCE_DIR}/tools/vxlandump.cpp + ${SOURCE_FILES_PCAP} + ) + set(SOURCE_FILES_PCAPCOMPARE ${PROJECT_SOURCE_DIR}/tools/pcapcompare.cpp ) -set(SOURCE_FILES_PKTMINERG_BASE - ${SOURCE_FILES_SYSHELP} - ${SOURCE_FILES_PCAP} - ${PROJECT_SOURCE_DIR}/src/socketgre.cpp - ${PROJECT_SOURCE_DIR}/src/pcaphandler.cpp - ${PROJECT_SOURCE_DIR}/src/statislog.cpp - ) +if(WIN32) + set(SOURCE_FILES_PKTMINERG_BASE + ${SOURCE_FILES_SYSHELP} + ${SOURCE_FILES_PCAP} + ${PROJECT_SOURCE_DIR}/src/socketgre.cpp + ${PROJECT_SOURCE_DIR}/src/socketvxlan.cpp + ${PROJECT_SOURCE_DIR}/src/pcaphandler.cpp + ${PROJECT_SOURCE_DIR}/src/statislog.cpp + ) +else() + set(SOURCE_FILES_PKTMINERG_BASE + ${SOURCE_FILES_SYSHELP} + ${SOURCE_FILES_PCAP} + ${PROJECT_SOURCE_DIR}/src/socketgre.cpp + ${PROJECT_SOURCE_DIR}/src/socketvxlan.cpp + ${PROJECT_SOURCE_DIR}/src/socketzmq.cpp + ${PROJECT_SOURCE_DIR}/src/pcaphandler.cpp + ${PROJECT_SOURCE_DIR}/src/statislog.cpp + ${PROJECT_SOURCE_DIR}/src/agent_status.cpp + ${PROJECT_SOURCE_DIR}/src/agent_control_plane.cpp + ) +endif() set(SOURCE_FILES_PKTMINERG ${SOURCE_FILES_PKTMINERG_BASE} @@ -229,9 +251,11 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) if(UNIX) set(PCAP_LIB pcap) set(BOOST_LIB boost_program_options.a boost_system.a boost_filesystem.a) + set(ZMQ_LIB zmq) else() set(PCAP_LIB wpcap Packet) - set(SOCKET_LIB ws2_32) + set(SOCKET_LIB zmq) + set(ZMQ_LIB ) endif() # bin -- gredemo @@ -248,6 +272,13 @@ if(WIN32) endif() target_link_libraries(gredump ${BOOST_LIB} ${PCAP_LIB} ${SOCKET_LIB}) +# bin --vxlandump +add_executable(vxlandump ${SOURCE_FILES_VXLANDUMP}) +if (WIN32) + set_target_properties(vxlandump PROPERTIES LINK_FLAGS "/MANIFESTUAC:\"level='requireAdministrator' uiAccess='false'\"") +endif () +target_link_libraries(vxlandump ${BOOST_LIB} ${PCAP_LIB} ${SOCKET_LIB}) + # bin -- pcapcompare add_executable(pcapcompare ${SOURCE_FILES_PCAPCOMPARE}) target_link_libraries(pcapcompare ${BOOST_LIB} ${PCAP_LIB} ${SOCKET_LIB}) @@ -257,7 +288,7 @@ add_executable(pktminerg ${SOURCE_FILES_PKTMINERG}) if(WIN32) set_target_properties(pktminerg PROPERTIES LINK_FLAGS "/MANIFESTUAC:\"level='requireAdministrator' uiAccess='false'\"") endif() -target_link_libraries(pktminerg ${BOOST_LIB} ${PCAP_LIB} ${SOCKET_LIB}) +target_link_libraries(pktminerg ${BOOST_LIB} ${PCAP_LIB} ${SOCKET_LIB} ${ZMQ_LIB}) if(UNIX AND NOT APPLE) # test @@ -275,7 +306,7 @@ if(UNIX AND NOT APPLE) ${TEST_DIR}/src/gtest-test-part.cc ${TEST_DIR}/src/gtest-typed-test.cc) add_executable(unittest ${SOURCE_FILES_UNITTEST} ${SOURCE_FILES_PKTMINERG_BASE}) - target_link_libraries(unittest ${BOOST_LIB} pcap pthread) + target_link_libraries(unittest ${BOOST_LIB} pcap pthread ${ZMQ_LIB}) set_target_properties(unittest PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/test/bin") endif() @@ -317,10 +348,12 @@ else() set(CPACK_DEB_COMPONENT_INSTALL ON) set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}_amd64) set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "amd64") + set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${PROJECT_SOURCE_DIR}/scripts/postinst") else () set(CPACK_GENERATOR "RPM") set(CPACK_RPM_COMPONENT_INSTALL ON) - set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.el6.${CMAKE_SYSTEM_PROCESSOR}) + set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.el6.${CMAKE_SYSTEM_PROCESSOR}) + set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE "${PROJECT_SOURCE_DIR}/scripts/postinst_rpm.sh") endif() #set(CPACK_COMPONENTS_ALL pktminerg) endif() diff --git a/INSTALL.md b/INSTALL.md index fa40e98bf..796b8c380 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -7,19 +7,83 @@ ```shell yum install libpcap wget ``` +Note: The default libpcap with TPACKET_V3 enabled has some performance issue. If performance is critical, you can remove libpcap and reinstall libpcap-1.8.1-6.fc27.x86_64.rpm or newer version which drops the TPACKET_V3 patch: http://rpm.pbone.net/index.php3/stat/22/idpl/50238989/com/changelog.html 2. Download and install the RPM package. Find the latest package from [Releases Page](https://github.com/Netis/packet-agent/releases). ```shell -wget https://github.com/Netis/packet-agent/releases/download/v0.3.3/netis-packet-agent-0.3.4.el6.x86_64.rpm -rpm -ivh netis-packet-agent-0.3.4.el6.x86_64.rpm +wget https://github.com/Netis/packet-agent/releases/download/v0.5.0/netis-packet-agent-0.5.0.el6.x86_64.rpm +rpm -ivh netis-packet-agent-0.5.0.el6.x86_64.rpm ``` + +## Ubuntu 18.04LTS + +1. Install libpcap and wget +```bash +sudo apt-get install libpcap-dev wget +``` + +2. Download and install the DEB package. Find the latest package from [Releases Page](https://github.com/Netis/packet-agent/releases). +```bash +wget https://github.com/Netis/packet-agent/releases/download/v0.5.0/netis-packet-agent-0.5.0_amd64.deb +sudo dpkg -i netis-packet-agent-0.5.0_amd64.deb +``` + +3. If libpcap.so.1 not found when running pktminerg, create softlink for libpcap.so.1 in suitable directory. +```bash +whereis libpcap.so +cd /path/to/libpcap.so +ln -s libpcap.so.x.y.z libpcap.so.1 +``` + + ## SUSE 12 -1. Download and install the RPM package. Find the latest package from [Releases Page](https://github.com/Netis/packet-agent/releases). +1. Install libpcap and wget ```shell -wget https://github.com/Netis/packet-agent/releases/download/v0.3.3/netis-packet-agent-0.3.4.el6.x86_64.rpm -rpm -ivh netis-packet-agent-0.3.4.el6.x86_64.rpm +yum install libpcap wget ``` + +2. Download and install the RPM package. Find the latest package from [Releases Page](https://github.com/Netis/packet-agent/releases). + +```shell +wget https://github.com/Netis/packet-agent/releases/download/v0.5.0/netis-packet-agent-0.5.0.el6.x86_64.rpm +rpm -ivh netis-packet-agent-0.5.0.el6.x86_64.rpm +``` + + +## Windows 7/8/10 x64 + +1. Download and Install [Winpcap](https://www.winpcap.org/install/bin/WinPcap_4_1_3.exe) of latest version. +2. Download and Install [Microsoft Visual C++ Redistributable for Visual Studio 2017 x64](https://aka.ms/vs/15/release/vc_redist.x64.exe). +3. Download and ZIP package. Find the latest package from [Releases Page](https://github.com/Netis/packet-agent/releases). +4. Extract pktminerg and other utilities from zip, and run it in cmd in Administrator Mode. + +Note: On Windows platform, you must use NIC's NT Device Name with format "\Device\NPF_{UUID}" as interface param. You can get it with following command: +``` + C:\> getmac /fo csv /v + "Connection Name","Network Adapter","Physical Address","Transport Name" + "Ethernet","Intel(R) Ethernet Connection (4) I219-V","8C-16-45-6B-53-B5","\Device\Tcpip_{4C25EA92-09DF-4FD3-A8B3-1B68E57443E2}" +``` +Take last field(Transport Name) and replace "Tcpip_" with "NPF_" as follow, then you can get interface param of Windows. +``` + \Device\NPF_{4C25EA92-09DF-4FD3-A8B3-1B68E57443E2} +``` +Use example: +``` + C:\> pktminerg -i \Device\NPF_{4C25EA92-09DF-4FD3-A8B3-1B68E57443E2} -r 172.24.103.201 + C:\> gredump -i \Device\NPF_{4C25EA92-09DF-4FD3-A8B3-1B68E57443E2} -o capture.pcap +``` + +## CentOS6 or CentOS 7 +1. Install the libpcap at first +```shell +yum install libpcap +``` +2. Install the packet agent from RPM package. Please find the latest package form [Releases Page](https://github.com/Netis/packet-agent/releases). +```shell +wget https://github.com/Netis/packet-agent/releases/download/v0.3.0/netis-packet-agent-0.3.0.el6.x86_64.rpm +rpm -ivh netis-packet-agent-0.3.0.el6.x86_64.rpm +``` \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md index d0b53b773..3aa3ba9bd 100755 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2018, Netis Technologies Co., Ltd. All rights reserved. +Copyright (c) 2018-2021, Netis Technologies Co., Ltd. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README-zh-Hans.md b/README-zh-Hans.md index 78c46f628..d114b6c0c 100644 --- a/README-zh-Hans.md +++ b/README-zh-Hans.md @@ -2,9 +2,9 @@ [English](README.md) ∙ 简体中文 ![packet agent's title](./img/title.jpg) -# Netis Packet Agent 0.3.4 +# Netis Packet Agent 0.5.0 -[![Stable release](https://img.shields.io/badge/version-0.3.4-green.svg)](https://github.com/Netis/packet-agent/releases/tag/0.3.4) +[![Stable release](https://img.shields.io/badge/version-0.5.0-green.svg)](https://github.com/Netis/packet-agent/releases/tag/0.5.0) [![Software License](https://img.shields.io/badge/license-BSD3-green.svg)](./LICENSE.md) @@ -35,14 +35,14 @@ yum install libpcap wget 2. 下载并安装RPM包。您可以从[这个地址](https://github.com/Netis/packet-agent/releases)获取最新版本的软件包。 ```bash -wget https://github.com/Netis/packet-agent/releases/download/v0.3.3/netis-packet-agent-0.3.4.el6.x86_64.rpm -rpm -ivh netis-packet-agent-0.3.4.el6.x86_64.rpm +wget https://github.com/Netis/packet-agent/releases/download/v0.5.0/netis-packet-agent-0.5.0.el6.x86_64.rpm +rpm -ivh netis-packet-agent-0.5.0.el6.x86_64.rpm ``` #### SUSE12 1. 下载并安装RPM包。您可以从[这个地址](https://github.com/Netis/packet-agent/releases)获取最新版本的软件包。 ```bash -wget https://github.com/Netis/packet-agent/releases/download/v0.3.3/netis-packet-agent-0.3.4.el6.x86_64.rpm -rpm -ivh netis-packet-agent-0.3.4.el6.x86_64.rpm +wget https://github.com/Netis/packet-agent/releases/download/v0.5.0/netis-packet-agent-0.5.0.el6.x86_64.rpm +rpm -ivh netis-packet-agent-0.5.0.el6.x86_64.rpm ``` #### Ubuntu 18.04LTS @@ -53,8 +53,8 @@ sudo apt-get install libpcap-dev wget 2. 下载并安装DEB包。您可以从[这个地址](https://github.com/Netis/packet-agent/releases)获取最新版本的软件包。 ```bash -wget https://github.com/Netis/packet-agent/releases/download/v0.3.3/netis-packet-agent-0.3.3_amd64.deb -sudo dpkg -i netis-packet-agent-0.3.3_amd64.deb +wget https://github.com/Netis/packet-agent/releases/download/v0.5.0/netis-packet-agent-0.5.0_amd64.deb +sudo dpkg -i netis-packet-agent-0.5.0_amd64.deb ``` 3. 如果提示libpcap.so找不到,到libpcap.so所在目录下创建libpcap.so.1软链接。 @@ -121,13 +121,14 @@ pktminerg -i eth0 -r 172.16.1.201 -M dont ## 文档/ 链接 * [安装](./INSTALL.md)和[使用](./USAGE.md)(仅英文版)。 * [构建条件及步骤](./BUILD.md)(仅英文版)。 -* [发布日志 / 路线图](./CHANGES.md)(仅英文版)。 +* [Packet-Agent 云平台性能评测](./docs/Packet-Agent性能评测.md)(仅中文版)。 +* [Packet-Agent libpcap 缓存与最大支持流量评测](./docs/Packet-Agent-libpcap缓存与最大支持流量评测.md)(仅中文版)。 ## 贡献 您可以fork本项目并提交Pull Request。我们欢迎所有开源社区的同学提交自己的贡献。 ## 许可证 -Copyright (c) 2018 Netis.
+Copyright (c) 2018 - 2020 Netis.
本项目库遵循下列许可证: - [BSD-3-Clause](./LICENSE.md). diff --git a/README.md b/README.md index 5d2b31168..4210ae411 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ English ∙ [简体中文](README-zh-Hans.md) ![packet agent's title](./img/title.jpg) -# Netis Packet Agent 0.3.4 +# Netis Packet Agent 0.5.0 -[![Stable release](https://img.shields.io/badge/version-0.3.4-green.svg)](https://github.com/Netis/packet-agent/releases/tag/0.3.4) +[![Stable release](https://img.shields.io/badge/version-0.5.0-green.svg)](https://github.com/Netis/packet-agent/releases/tag/0.5.0) [![Software License](https://img.shields.io/badge/license-BSD3-green.svg)](./LICENSE.md) ## What is Netis Packet Agent? @@ -30,20 +30,20 @@ With 3 utilities: #### CentOS 6/7 and RedHat 7 1. Install libpcap and wget ```bash -yum install libpcap wget +yum install libpcap wget zeromq ``` 2. Download and install the RPM package. Find the latest package from [Releases Page](https://github.com/Netis/packet-agent/releases). ```bash -wget https://github.com/Netis/packet-agent/releases/download/v0.3.3/netis-packet-agent-0.3.4.el6.x86_64.rpm -rpm -ivh netis-packet-agent-0.3.4.el6.x86_64.rpm +wget https://github.com/Netis/packet-agent/releases/download/v0.5.0/netis-packet-agent-0.5.0.el6.x86_64.rpm +rpm -ivh netis-packet-agent-0.5.0.el6.x86_64.rpm ``` #### SUSE 12 1. Download and install the RPM package. Find the latest package from [Releases Page](https://github.com/Netis/packet-agent/releases). ```bash -wget https://github.com/Netis/packet-agent/releases/download/v0.3.3/netis-packet-agent-0.3.4.el6.x86_64.rpm -rpm -ivh netis-packet-agent-0.3.4.el6.x86_64.rpm +wget https://github.com/Netis/packet-agent/releases/download/v0.5.0/netis-packet-agent-0.5.0.el6.x86_64.rpm +rpm -ivh netis-packet-agent-0.5.0.el6.x86_64.rpm ``` @@ -55,8 +55,8 @@ sudo apt-get install libpcap-dev wget 2. Download and install the DEB package. Find the latest package from [Releases Page](https://github.com/Netis/packet-agent/releases). ```bash -wget https://github.com/Netis/packet-agent/releases/download/v0.3.3/netis-packet-agent-0.3.3_amd64.deb -sudo dpkg -i netis-packet-agent-0.3.3_amd64.deb +wget https://github.com/Netis/packet-agent/releases/download/v0.5.0/netis-packet-agent-0.5.0_amd64.deb +sudo dpkg -i netis-packet-agent-0.5.0_amd64.deb ``` 3. If libpcap.so.1 not found when running pktminerg, create softlink for libpcap.so.1 in suitable directory. @@ -92,6 +92,8 @@ Use example: ``` +## Engineering team contacts +* [E-mail us.](mailto:developer@netis.com)
### Usage @@ -134,7 +136,7 @@ For build precondition and steps, please refer to this [document](./BUILD.md). Fork the project and send pull requests. We welcome pull requests from members of all open source community. ## License -Copyright (c) 2018 Netis.
+Copyright (c) 2018 - 2020 Netis.
The content of this repository bound by the following licenses: - The computer software is licensed under the [BSD-3-Clause](./LICENSE.md). diff --git a/USAGE.md b/USAGE.md index 1f88a157f..b62378538 100644 --- a/USAGE.md +++ b/USAGE.md @@ -19,6 +19,11 @@ Allowed options: for test -r [ --remoteip ] IPs set gre remote IPs, seperate by ',' Example: -r 8.8.4.4,8.8.8.8 + -z [ --zmq_port ] ZMQ_PORT (=0) set remote zeromq server port to receive + packets reliably; ZMQ_PORT default value 0 + means disable. + -m [ --zmq_hwm ] ZMQ_HWM (=100) set zeromq queue high watermark; ZMQ_HWM + default value 100. -k [ --keybit ] BIT (=1) set gre key bit; BIT defaults 1 -s [ --snaplen ] LENGTH (=2048) set snoop packet snaplen; LENGTH defaults 2048 and units byte @@ -32,10 +37,12 @@ Allowed options: --cpu ID set cpu affinity ID (Not supported on Windows platform) --expression FILTER filter packets with FILTER; FILTER as same as tcpdump BPF expression syntax + --control CONTROL_PORT set zmq listen port for agent daemon control. Control server won't + be up if this option is not set.(Not supported on Windows platform). --dump specify dump file, mostly for integrated test - --nofilter force no filter; only use when you confirm - that the snoop interface is different from - the gre interface + --nofilter force no filter; In online mode, only use when GRE interface + is set via CLI, AND you confirm that the snoop interface is + different from the gre interface. ``` @@ -57,7 +64,13 @@ Send GRE packets from this binded device. Sending will be failed when this devic * remoteip, keybit
Parameters of GRE channel: remoteip:GRE channel remote IP addresss (required) -keybit:GRE protocol keybit parameter to distinguish the channel to remote IP +keybit:GRE protocol keybit parameter to distinguish the channel to remote IP, high 4 bit is reserved for direction. +
+ +* zmq_port, zmq_hwm
+Parameters of zeromq: +zmq_port: set remote zeromq server port to receive packets reliably; ZMQ_PORT default value 0 means disable. +zmq_hwm: set zeromq queue high watermark; ZMQ_HWM default value 100.
* cpu, priority
@@ -79,6 +92,54 @@ expression: This parameter is used to match and filter the packets (syntax is sa This parameter will be invalid if "nofilter" parameter is set.
+* control
+control: set zmq listen port for agent daemon control. +From version 0.3.6, packet-agent's control plane support daemon service via zmq(REQ/RSP), such as packet-agent status query, and packet-agent run as zmq server. +The exchange data format list in C Language as below : +``` +// request and response data format, between zmq client and server +typedef struct msg { + /* header */ + uint32_t magic; // must be 0x50 0x4D 0x32 0x30 in order. + uint32_t msglength; // msg length, include header, in bytes. + uint32_t action; // list below + uint32_t query_id; // the query id to identify each client for req flush + + /* body */ + char body[MAX_MSG_CONTENT_LENGTH]; +} __attribute__((packed)) msg_t, * msg_ptr_t; + + +// support action now +typedef enum msg_action_req_type { + MSG_ACTION_REQ_INVALID = 0x0000, + MSG_ACTION_REQ_QUERY_STATUS = 0x0001, + MSG_ACTION_REQ_MAX +} msg_act_req_type_e; + +// action MSG_ACTION_REQ_QUERY_STATUS's response data body. +typedef struct msg_status { + uint32_t ver; + uint32_t start_time; + uint32_t last_time; + uint32_t total_cap_bytes; + uint32_t total_cap_packets; + uint32_t total_cap_drop_count; + uint32_t total_filter_drop_count; + uint32_t total_fwd_drop_count; +}__attribute__((packed)) msg_status_t, * msg_status_ptr_t; + +``` + + 1. Control server won't be up if this option is not set. + 2. Not supported on Windows platform. +
+ + + + + + ### Examples * Network interface example ``` @@ -185,3 +246,18 @@ Exit after receiving count packets. Default=0, No limit if count <= 0. gredump -i eth0 -o /path/to/gredump_output.pcap ``` +## Example +* Network interface example
+pktminerg -i eth0 -r 172.16.1.201 + +* Pcap file example
+pktminerg -f sample.pcap -r 172.16.1.201 + +* Filter example
+pktminerg -i eth0 -r 172.16.1.201 --expression '172.16.1.12' + +* CPU affinity and high priority example
+pktminerg -i eth0 -r 172.16.1.201 --cpu 1 -p + +* nofilter example, the packet capture network interface must different from the GRE output interface
+pktminerg -i eth0 -r 172.16.1.201 --nofilter diff --git a/docker/K8S_traffic_mirror.md b/docker/K8S_traffic_mirror.md new file mode 100644 index 000000000..7ea005f92 --- /dev/null +++ b/docker/K8S_traffic_mirror.md @@ -0,0 +1,315 @@ +# 摘要 +  随着应用开发和部署流程进一步跟上需求迭代速度,调度资源更灵活、方便集群化部署的容器架构逐渐推广开来。相比虚拟机为单位的云架构,封闭程度更高的容器化应用更难以实现流量采集。本文介绍了Kubernetes环境流量采集的三种方案。
+ +# 需要解决的问题 +  Kubernetes架构中,应用连同其依赖组件被打包为高度独立的单元,称为「容器」。容器化的业务应用尽可能降低了对外部环境的依赖程度,因此可以由控制器快速创建、配置和调整,灵活性非常高。但容器是一个相对完整而封闭的结构单元,无法直接在其镜像内部署流量采集组件。
+ +# 技术背景 +  应用虽然被打包为一个个容器,但系统对其管理是通过名为Pod的结构实现的:一个Pod中可以放置单个或多个应用容器,这些同Pod的容器共享Pod内的网络、存储等资源,彼此之间可见。
+  通过补丁,可以避免定义整个对象,只需要定义希望更改的部分。只需要定义新增的元素就可以更新一个列表。列表中已有的元素仍然保留,新增的元素和已有的元素会被合并。
+  准入控制器是一段代码,会拦截 Kubernetes API Server 收到的请求,拦截发生在认证和鉴权完成之后,对象进行持久化之前。可以定义两种类型的 Admission webhook:Validating 和 Mutating。Validating 类型的 Webhook 可以根据自定义的准入策略决定是否拒绝请求;Mutating 类型的 Webhook 可以根据自定义配置来对请求进行编辑。
+ +# 方案一:修改 yaml 配置文件 +* 直接修改YAML文件,直接将流量采集的镜像部署到被监控应用的同一个POD中去: +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment +spec: + selector: + matchLabels: + app: nginx + replicas: 2 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx:1.7.9 + ports: + - containerPort: 80 + - name: monitor + image: docker.io/s1240zsw/centos-packet-agent:v1 + stdin: true + tty: true +``` + +# 方案二:补丁命令 +* Patch deployment,应用部署后通过修改补丁将流量采集的镜像部署到被监控应用的同一个POD中去 +```console +kubectl patch deployment nginx-deployment -p '{"spec":{"template":{"spec":{"containers":[{"name":"monitor","image":"docker.io/s1240zsw/centos-packet-agent:v1","stdin":true,"tty":true}]}}}}' +``` + +# 方案三:WebHook +* WebHook,通过监控pod的启动停止行为,在需要监控的pod启动的时候自动将将流量采集的镜像部署到被监控应用的同一个POD中去 + 1. 生成密钥 + ```console + ./webhook-create-signed-cert.sh \ + --service sidecar-injector-webhook-svc \ + --secret sidecar-injector-webhook-certs \ + --namespace default + ``` + * webhook-create-signed-cert.sh + ```bash + #!/bin/bash + set -e + usage() { + cat <> ${tmpdir}/csr.conf + [req] + req_extensions = v3_req + distinguished_name = req_distinguished_name + [req_distinguished_name] + [ v3_req ] + basicConstraints = CA:FALSE + keyUsage = nonRepudiation, digitalSignature, keyEncipherment + extendedKeyUsage = serverAuth + subjectAltName = @alt_names + [alt_names] + DNS.1 = ${service} + DNS.2 = ${service}.${namespace} + DNS.3 = ${service}.${namespace}.svc + EOF + + openssl genrsa -out ${tmpdir}/server-key.pem 2048 + openssl req -new -key ${tmpdir}/server-key.pem -subj "/CN=${service}.${namespace}.svc" -out ${tmpdir}/server.csr -config ${tmpdir}/csr.conf + + # clean-up any previously created CSR for our service. Ignore errors if not present. + kubectl delete csr ${csrName} 2>/dev/null || true + + # create server cert/key CSR and send to k8s API + cat <&2 + exit 1 + fi + + echo ${serverCert} | openssl base64 -d -A -out ${tmpdir}/server-cert.pem + # create the secret with CA cert and server cert/key + kubectl create secret generic ${secret} \ + --from-file=key.pem=${tmpdir}/server-key.pem \ + --from-file=cert.pem=${tmpdir}/server-cert.pem \ + --dry-run -o yaml | + kubectl -n ${namespace} apply -f - + ``` + 2. 部署密钥 + ```console + cat mutatingwebhook.yaml | \ + webhook-patch-ca-bundle.sh > \ + mutatingwebhook-ca-bundle.yaml + ``` + * webhook-patch-ca-bundle.sh + ```bash + #!/bin/bash + ROOT=$(cd $(dirname $0)/../../; pwd) + set -o errexit + set -o nounset + set -o pipefail + export CA_BUNDLE=$(kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.certificate-authority-data}') + + if command -v envsubst >/dev/null 2>&1; then + envsubst + else + sed -e "s|\${CA_BUNDLE}|${CA_BUNDLE}|g" + fi + ``` + * mutatingwebhook.yaml + ```yaml + apiVersion: admissionregistration.k8s.io/v1beta1 + kind: MutatingWebhookConfiguration + metadata: + name: sidecar-injector-webhook-cfg + labels: + app: sidecar-injector + webhooks: + - name: sidecar-injector.morven.me + clientConfig: + service: + name: sidecar-injector-webhook-svc + namespace: default + path: "/mutate" + caBundle: ${CA_BUNDLE} + rules: + - operations: [ "CREATE" ] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + namespaceSelector: + matchLabels: + sidecar-injector: enabled + ``` + 3. 部署流量监控镜像 + ```bash + kubectl create -f configmap.yaml + kubectl create -f deployment.yaml + kubectl create -f service.yaml + kubectl create -f mutatingwebhook-ca-bundle.yaml + ``` + * configmap.yaml + ```yaml + apiVersion: v1 + kind: ConfigMap + metadata: + name: sidecar-injector-webhook-configmap + data: + sidecarconfig.yaml: | + containers: + - name: sidecar-monitor + image: docker.io/s1240zsw/centos-packet-agent:v1 + stdin: true + tty: true + ``` + + * deployment.yaml + ```yaml + apiVersion: extensions/v1beta1 + kind: Deployment + metadata: + name: sidecar-injector-webhook-deployment + labels: + app: sidecar-injector + spec: + replicas: 1 + template: + metadata: + labels: + app: sidecar-injector + spec: + containers: + - name: sidecar-injector + image: morvencao/sidecar-injector:v1 + imagePullPolicy: IfNotPresent + args: + - -sidecarCfgFile=/etc/webhook/config/sidecarconfig.yaml + - -tlsCertFile=/etc/webhook/certs/cert.pem + - -tlsKeyFile=/etc/webhook/certs/key.pem + - -alsologtostderr + - -v=4 + - 2>&1 + volumeMounts: + - name: webhook-certs + mountPath: /etc/webhook/certs + readOnly: true + - name: webhook-config + mountPath: /etc/webhook/config + volumes: + - name: webhook-certs + secret: + secretName: sidecar-injector-webhook-certs + - name: webhook-config + configMap: + name: sidecar-injector-webhook-configmap + ``` + * service.yaml + ```yaml + apiVersion: v1 + kind: Service + metadata: + name: sidecar-injector-webhook-svc + labels: + app: sidecar-injector + spec: + ports: + - port: 443 + targetPort: 443 + selector: + app: sidecar-injector + ``` + 4. 给需要监控的应用打上标签 + ```console + kubectl patch deployment nginx-deployment -p '{"spec":{"template":{"metadata":{"annotations":{"sidecar-injector-webhook.morven.me/inject": "true"}}}}}' + ``` + +# 结论 +  优先采用修改yaml文件的方法,如果没有修改yaml文件的权限,那么可以采用Patch deployment方法。如果以上方法都不能用最后再采用WebHook方法。
+ +# 参考 +1. [Istio Sidecar 注入过程解密](https://istio.io/zh/blog/2019/data-plane-setup/) +2. [Diving into Kubernetes MutatingAdmissionWebhook](https://github.com/morvencao/kube-mutating-webhook-tutorial/blob/master/medium-article.md) + diff --git "a/docs/Packet-Agent-libpcap\347\274\223\345\255\230\344\270\216\346\234\200\345\244\247\346\224\257\346\214\201\346\265\201\351\207\217\350\257\204\346\265\213.md" "b/docs/Packet-Agent-libpcap\347\274\223\345\255\230\344\270\216\346\234\200\345\244\247\346\224\257\346\214\201\346\265\201\351\207\217\350\257\204\346\265\213.md" new file mode 100644 index 000000000..1817110d0 --- /dev/null +++ "b/docs/Packet-Agent-libpcap\347\274\223\345\255\230\344\270\216\346\234\200\345\244\247\346\224\257\346\214\201\346\265\201\351\207\217\350\257\204\346\265\213.md" @@ -0,0 +1,22 @@ +# Packet-Agent libpcap 缓存与最大支持流量评测 + +# 测试环境与方法 + +pktminerg version 0.3.2 (rev: 7d844a7 build: 2019-01-21 10:27:50) +libpcap version 1.5.3 + +8 核 vSphere 虚拟机:Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz +内存 16GB + +使用 --buffsize 参数控制 pktminerg libpcap 缓存大小,使用tcpreplay往网卡发包,逐次增加发包速率,记录 pktminerg 出现丢包时的发包速率。 + +# 测试结果 + + +|libpcap buffsize| 进程内存占用 | 最大支持流量 | +|----------------|--------------|--------------| +|18 MB | 32 MB | 549 Mbps| +|36 MB | 50 MB | 705 Mbps| +|64 MB | 79 MB | 862 Mbps| +|128 MB | 145 MB | 900 Mbps| + diff --git "a/docs/Packet-Agent\346\200\247\350\203\275\350\257\204\346\265\213.md" "b/docs/Packet-Agent\346\200\247\350\203\275\350\257\204\346\265\213.md" index de7e1a1ef..a0483f91e 100644 --- "a/docs/Packet-Agent\346\200\247\350\203\275\350\257\204\346\265\213.md" +++ "b/docs/Packet-Agent\346\200\247\350\203\275\350\257\204\346\265\213.md" @@ -13,10 +13,10 @@ libpcap version 1.5.3 | | 2 cpu | 8 cpu | 12 cpu | |-----|-------|-------|--------| -|通用型 centos7.6|内存占用 508.8 M
![image](../img/image2019-7-26_12-19-28.png)|内存占用 508.8 M
![image](../img/image2019-7-26_12-20-15.png)|内存占用 508.8 M
![image](../img/image2019-7-26_12-20-33.png)| -|高主频 centos7.6|内存占用 508.8 M
![image](../img/image2019-7-26_12-21-22.png)|内存占用 508.8 M
![image](../img/image2019-7-26_12-21-51.png)|内存占用 508.8 M
![image](../img/image2019-7-26_12-22-37.png)| -|通用型 suse12.2|内存占用:280.2 M。CPU顶峰:90.3%,1175.5 Mbps
![image](../img/image2019-7-29_11-22-40.png)|内存占用:280.2 M
![image](../img/image2019-7-26_16-52-16.png)|内存占用:280.2 M
![image](../img/image2019-7-26_16-51-39.png)| -|高主频 suse12.2|内存占用:280.2 M。CPU顶峰:97.47%,1175.5 Mbps
![image](../img/image2019-7-29_11-23-48.png)|内存占用:280.2 M
![image](../img/image2019-7-26_16-53-32.png)|内存占用:280.2 M
![image](../img/image2019-7-26_16-55-46.png)| +|通用型 centos7.6|内存占用 508.8 M
![image](../img/ali-1-1.png)|内存占用 508.8 M
![image](../img/ali-1-2.png)|内存占用 508.8 M
![image](../img/ali-1-3.png)| +|高主频 centos7.6|内存占用 508.8 M
![image](../img/ali-2-1.png)|内存占用 508.8 M
![image](../img/ali-2-2.png)|内存占用 508.8 M
![image](../img/ali-2-3.png)| +|通用型 suse12.2|内存占用:280.2 M。CPU顶峰:90.3%,1175.5 Mbps
![image](../img/ali-3-1.png)|内存占用:280.2 M
![image](../img/ali-3-2.png)|内存占用:280.2 M
![image](../img/ali-3-3.png)| +|高主频 suse12.2|内存占用:280.2 M。CPU顶峰:97.47%,1175.5 Mbps
![image](../img/ali-4-1.png)|内存占用:280.2 M
![image](../img/ali-4-2.png)|内存占用:280.2 M
![image](../img/ali-4-3.png)| # 阿里云机器配置 @@ -34,10 +34,10 @@ libpcap version 1.5.3 | | 2 cpu | 8 cpu | 12 cpu | |-----|-------|-------|--------| -|通用型 centos7.6|内存占用 508.8 M
![image](../img/image2019-8-2_10-28-14.png)|内存占用 508.8 M
![image](../img/image2019-8-2_10-29-16.png)|内存占用 508.8 M
![image](../img/image2019-8-2_10-30-17.png)| -|高主频 centos7.6|内存占用 508.8 M
![image](../img/image2019-8-2_10-31-39.png)|内存占用 508.8 M
![image](../img/image2019-8-2_10-32-38.png)|内存占用 508.8 M
![image](../img/image2019-8-2_10-33-32.png)| -|通用型 suse12.2|内存占用:280.2 M
![image](../img/image2019-8-1_10-22-54.png)|内存占用:280.2 M
![image](../img/image2019-8-1_10-23-45.png)|内存占用:280.2 M
![image](../img/image2019-8-1_10-24-32.png)| -|高主频 suse12.2|内存占用:280.2 M
![image](../img/image2019-8-1_10-25-31.png)|内存占用:280.2 M
![image](../img/image2019-8-1_10-26-12.png)|内存占用:280.2 M
![image](../img/image2019-8-1_10-26-49.png)| +|通用型 centos7.6|内存占用 508.8 M
![image](../img/aws-1-1.png)|内存占用 508.8 M
![image](../img/aws-1-2.png)|内存占用 508.8 M
![image](../img/aws-1-3.png)| +|高主频 centos7.6|内存占用 508.8 M
![image](../img/aws-2-1.png)|内存占用 508.8 M
![image](../img/aws-2-2.png)|内存占用 508.8 M
![image](../img/aws-2-3.png)| +|通用型 suse12.2|内存占用:280.2 M
![image](../img/aws-3-1.png)|内存占用:280.2 M
![image](../img/aws-3-2.png)|内存占用:280.2 M
![image](../img/aws-3-3.png)| +|高主频 suse12.2|内存占用:280.2 M
![image](../img/aws-4-1.png)|内存占用:280.2 M
![image](../img/aws-4-2.png)|内存占用:280.2 M
![image](../img/aws-4-3.png)| # aws机器配置 diff --git a/img/ali-1-1.png b/img/ali-1-1.png new file mode 100644 index 000000000..721a27c95 Binary files /dev/null and b/img/ali-1-1.png differ diff --git a/img/ali-1-2.png b/img/ali-1-2.png new file mode 100644 index 000000000..4ea6be51c Binary files /dev/null and b/img/ali-1-2.png differ diff --git a/img/ali-1-3.png b/img/ali-1-3.png new file mode 100644 index 000000000..616242939 Binary files /dev/null and b/img/ali-1-3.png differ diff --git a/img/ali-2-1.png b/img/ali-2-1.png new file mode 100644 index 000000000..547a69a19 Binary files /dev/null and b/img/ali-2-1.png differ diff --git a/img/ali-2-2.png b/img/ali-2-2.png new file mode 100644 index 000000000..0ecea94af Binary files /dev/null and b/img/ali-2-2.png differ diff --git a/img/ali-2-3.png b/img/ali-2-3.png new file mode 100644 index 000000000..f53deda57 Binary files /dev/null and b/img/ali-2-3.png differ diff --git a/img/ali-3-1.png b/img/ali-3-1.png new file mode 100644 index 000000000..204b7878a Binary files /dev/null and b/img/ali-3-1.png differ diff --git a/img/ali-3-2.png b/img/ali-3-2.png new file mode 100644 index 000000000..bb0780840 Binary files /dev/null and b/img/ali-3-2.png differ diff --git a/img/ali-3-3.png b/img/ali-3-3.png new file mode 100644 index 000000000..b2305cb57 Binary files /dev/null and b/img/ali-3-3.png differ diff --git a/img/ali-4-1.png b/img/ali-4-1.png new file mode 100644 index 000000000..f523039e5 Binary files /dev/null and b/img/ali-4-1.png differ diff --git a/img/ali-4-2.png b/img/ali-4-2.png new file mode 100644 index 000000000..81533e257 Binary files /dev/null and b/img/ali-4-2.png differ diff --git a/img/ali-4-3.png b/img/ali-4-3.png new file mode 100644 index 000000000..cf39f1312 Binary files /dev/null and b/img/ali-4-3.png differ diff --git a/img/aws-1-1.png b/img/aws-1-1.png new file mode 100644 index 000000000..e23b2cd9b Binary files /dev/null and b/img/aws-1-1.png differ diff --git a/img/aws-1-2.png b/img/aws-1-2.png new file mode 100644 index 000000000..1d55774b3 Binary files /dev/null and b/img/aws-1-2.png differ diff --git a/img/aws-1-3.png b/img/aws-1-3.png new file mode 100644 index 000000000..e3e31c427 Binary files /dev/null and b/img/aws-1-3.png differ diff --git a/img/aws-2-1.png b/img/aws-2-1.png new file mode 100644 index 000000000..4cfd433f3 Binary files /dev/null and b/img/aws-2-1.png differ diff --git a/img/aws-2-2.png b/img/aws-2-2.png new file mode 100644 index 000000000..a5e7c9d1b Binary files /dev/null and b/img/aws-2-2.png differ diff --git a/img/aws-2-3.png b/img/aws-2-3.png new file mode 100644 index 000000000..e5203038e Binary files /dev/null and b/img/aws-2-3.png differ diff --git a/img/aws-3-1.png b/img/aws-3-1.png new file mode 100644 index 000000000..4e1d7a2cb Binary files /dev/null and b/img/aws-3-1.png differ diff --git a/img/aws-3-2.png b/img/aws-3-2.png new file mode 100644 index 000000000..046146e43 Binary files /dev/null and b/img/aws-3-2.png differ diff --git a/img/aws-3-3.png b/img/aws-3-3.png new file mode 100644 index 000000000..e96da3ead Binary files /dev/null and b/img/aws-3-3.png differ diff --git a/img/aws-4-1.png b/img/aws-4-1.png new file mode 100644 index 000000000..e549c9986 Binary files /dev/null and b/img/aws-4-1.png differ diff --git a/img/aws-4-2.png b/img/aws-4-2.png new file mode 100644 index 000000000..c588b1d36 Binary files /dev/null and b/img/aws-4-2.png differ diff --git a/img/aws-4-3.png b/img/aws-4-3.png new file mode 100644 index 000000000..7e8699365 Binary files /dev/null and b/img/aws-4-3.png differ diff --git a/img/image2019-7-26_12-19-28.png b/img/image2019-7-26_12-19-28.png deleted file mode 100644 index fa5c78492..000000000 Binary files a/img/image2019-7-26_12-19-28.png and /dev/null differ diff --git a/img/image2019-7-26_12-20-15.png b/img/image2019-7-26_12-20-15.png deleted file mode 100644 index dde1be3a9..000000000 Binary files a/img/image2019-7-26_12-20-15.png and /dev/null differ diff --git a/img/image2019-7-26_12-20-33.png b/img/image2019-7-26_12-20-33.png deleted file mode 100644 index d72a23d45..000000000 Binary files a/img/image2019-7-26_12-20-33.png and /dev/null differ diff --git a/img/image2019-7-26_12-21-22.png b/img/image2019-7-26_12-21-22.png deleted file mode 100644 index a382ac796..000000000 Binary files a/img/image2019-7-26_12-21-22.png and /dev/null differ diff --git a/img/image2019-7-26_12-21-51.png b/img/image2019-7-26_12-21-51.png deleted file mode 100644 index b73502824..000000000 Binary files a/img/image2019-7-26_12-21-51.png and /dev/null differ diff --git a/img/image2019-7-26_12-22-37.png b/img/image2019-7-26_12-22-37.png deleted file mode 100644 index 6fc884cd7..000000000 Binary files a/img/image2019-7-26_12-22-37.png and /dev/null differ diff --git a/img/image2019-7-26_16-51-39.png b/img/image2019-7-26_16-51-39.png deleted file mode 100644 index bd5ebf8ac..000000000 Binary files a/img/image2019-7-26_16-51-39.png and /dev/null differ diff --git a/img/image2019-7-26_16-52-16.png b/img/image2019-7-26_16-52-16.png deleted file mode 100644 index e9f372ff6..000000000 Binary files a/img/image2019-7-26_16-52-16.png and /dev/null differ diff --git a/img/image2019-7-26_16-53-32.png b/img/image2019-7-26_16-53-32.png deleted file mode 100644 index efffdbc9d..000000000 Binary files a/img/image2019-7-26_16-53-32.png and /dev/null differ diff --git a/img/image2019-7-26_16-55-46.png b/img/image2019-7-26_16-55-46.png deleted file mode 100644 index d62f2d8bb..000000000 Binary files a/img/image2019-7-26_16-55-46.png and /dev/null differ diff --git a/img/image2019-7-29_11-22-40.png b/img/image2019-7-29_11-22-40.png deleted file mode 100644 index 9f1c45093..000000000 Binary files a/img/image2019-7-29_11-22-40.png and /dev/null differ diff --git a/img/image2019-7-29_11-23-48.png b/img/image2019-7-29_11-23-48.png deleted file mode 100644 index 06e4ae892..000000000 Binary files a/img/image2019-7-29_11-23-48.png and /dev/null differ diff --git a/img/image2019-8-1_10-22-54.png b/img/image2019-8-1_10-22-54.png deleted file mode 100644 index cb4593b5c..000000000 Binary files a/img/image2019-8-1_10-22-54.png and /dev/null differ diff --git a/img/image2019-8-1_10-23-45.png b/img/image2019-8-1_10-23-45.png deleted file mode 100644 index 0ffe22baf..000000000 Binary files a/img/image2019-8-1_10-23-45.png and /dev/null differ diff --git a/img/image2019-8-1_10-24-32.png b/img/image2019-8-1_10-24-32.png deleted file mode 100644 index 31286c8cb..000000000 Binary files a/img/image2019-8-1_10-24-32.png and /dev/null differ diff --git a/img/image2019-8-1_10-25-31.png b/img/image2019-8-1_10-25-31.png deleted file mode 100644 index f56e2e300..000000000 Binary files a/img/image2019-8-1_10-25-31.png and /dev/null differ diff --git a/img/image2019-8-1_10-26-12.png b/img/image2019-8-1_10-26-12.png deleted file mode 100644 index bafb88d36..000000000 Binary files a/img/image2019-8-1_10-26-12.png and /dev/null differ diff --git a/img/image2019-8-1_10-26-49.png b/img/image2019-8-1_10-26-49.png deleted file mode 100644 index de40fcead..000000000 Binary files a/img/image2019-8-1_10-26-49.png and /dev/null differ diff --git a/img/image2019-8-2_10-28-14.png b/img/image2019-8-2_10-28-14.png deleted file mode 100644 index 5768e7a14..000000000 Binary files a/img/image2019-8-2_10-28-14.png and /dev/null differ diff --git a/img/image2019-8-2_10-29-16.png b/img/image2019-8-2_10-29-16.png deleted file mode 100644 index 472982fa4..000000000 Binary files a/img/image2019-8-2_10-29-16.png and /dev/null differ diff --git a/img/image2019-8-2_10-30-17.png b/img/image2019-8-2_10-30-17.png deleted file mode 100644 index 8834025f5..000000000 Binary files a/img/image2019-8-2_10-30-17.png and /dev/null differ diff --git a/img/image2019-8-2_10-31-39.png b/img/image2019-8-2_10-31-39.png deleted file mode 100644 index 158af3583..000000000 Binary files a/img/image2019-8-2_10-31-39.png and /dev/null differ diff --git a/img/image2019-8-2_10-32-38.png b/img/image2019-8-2_10-32-38.png deleted file mode 100644 index 0b75d9c8d..000000000 Binary files a/img/image2019-8-2_10-32-38.png and /dev/null differ diff --git a/img/image2019-8-2_10-33-32.png b/img/image2019-8-2_10-33-32.png deleted file mode 100644 index d36b83a18..000000000 Binary files a/img/image2019-8-2_10-33-32.png and /dev/null differ diff --git a/include/zmq.hpp b/include/zmq.hpp new file mode 100644 index 000000000..d02a208f9 --- /dev/null +++ b/include/zmq.hpp @@ -0,0 +1,2688 @@ +/* + Copyright (c) 2016-2017 ZeroMQ community + Copyright (c) 2009-2011 250bpm s.r.o. + Copyright (c) 2011 Botond Ballo + Copyright (c) 2007-2009 iMatix Corporation + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +*/ + +#ifndef __ZMQ_HPP_INCLUDED__ +#define __ZMQ_HPP_INCLUDED__ + +#ifdef _WIN32 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#endif + +// included here for _HAS_CXX* macros +#include + +#if defined(_MSVC_LANG) +#define CPPZMQ_LANG _MSVC_LANG +#else +#define CPPZMQ_LANG __cplusplus +#endif +// overwrite if specific language macros indicate higher version +#if defined(_HAS_CXX14) && _HAS_CXX14 && CPPZMQ_LANG < 201402L +#undef CPPZMQ_LANG +#define CPPZMQ_LANG 201402L +#endif +#if defined(_HAS_CXX17) && _HAS_CXX17 && CPPZMQ_LANG < 201703L +#undef CPPZMQ_LANG +#define CPPZMQ_LANG 201703L +#endif + +// macros defined if has a specific standard or greater +#if CPPZMQ_LANG >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) +#define ZMQ_CPP11 +#endif +#if CPPZMQ_LANG >= 201402L +#define ZMQ_CPP14 +#endif +#if CPPZMQ_LANG >= 201703L +#define ZMQ_CPP17 +#endif + +#if defined(ZMQ_CPP14) && !defined(_MSC_VER) +#define ZMQ_DEPRECATED(msg) [[deprecated(msg)]] +#elif defined(_MSC_VER) +#define ZMQ_DEPRECATED(msg) __declspec(deprecated(msg)) +#elif defined(__GNUC__) +#define ZMQ_DEPRECATED(msg) __attribute__((deprecated(msg))) +#endif + +#if defined(ZMQ_CPP17) +#define ZMQ_NODISCARD [[nodiscard]] +#else +#define ZMQ_NODISCARD +#endif + +#if defined(ZMQ_CPP11) +#define ZMQ_NOTHROW noexcept +#define ZMQ_EXPLICIT explicit +#define ZMQ_OVERRIDE override +#define ZMQ_NULLPTR nullptr +#define ZMQ_CONSTEXPR_FN constexpr +#define ZMQ_CONSTEXPR_VAR constexpr +#define ZMQ_CPP11_DEPRECATED(msg) ZMQ_DEPRECATED(msg) +#else +#define ZMQ_NOTHROW throw() +#define ZMQ_EXPLICIT +#define ZMQ_OVERRIDE +#define ZMQ_NULLPTR 0 +#define ZMQ_CONSTEXPR_FN +#define ZMQ_CONSTEXPR_VAR const +#define ZMQ_CPP11_DEPRECATED(msg) +#endif +#if defined(ZMQ_CPP14) && (!defined(_MSC_VER) || _MSC_VER > 1900) +#define ZMQ_EXTENDED_CONSTEXPR +#endif +#if defined(ZMQ_CPP17) +#define ZMQ_INLINE_VAR inline +#else +#define ZMQ_INLINE_VAR +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#ifdef ZMQ_CPP11 +#include +#include +#include +#include +#endif + +#if defined(__has_include) && defined(ZMQ_CPP17) +#define CPPZMQ_HAS_INCLUDE_CPP17(X) __has_include(X) +#else +#define CPPZMQ_HAS_INCLUDE_CPP17(X) 0 +#endif + +#if CPPZMQ_HAS_INCLUDE_CPP17() && !defined(CPPZMQ_HAS_OPTIONAL) +#define CPPZMQ_HAS_OPTIONAL 1 +#endif +#ifndef CPPZMQ_HAS_OPTIONAL +#define CPPZMQ_HAS_OPTIONAL 0 +#elif CPPZMQ_HAS_OPTIONAL +#include +#endif + +#if CPPZMQ_HAS_INCLUDE_CPP17() && !defined(CPPZMQ_HAS_STRING_VIEW) +#define CPPZMQ_HAS_STRING_VIEW 1 +#endif +#ifndef CPPZMQ_HAS_STRING_VIEW +#define CPPZMQ_HAS_STRING_VIEW 0 +#elif CPPZMQ_HAS_STRING_VIEW +#include +#endif + +/* Version macros for compile-time API version detection */ +#define CPPZMQ_VERSION_MAJOR 4 +#define CPPZMQ_VERSION_MINOR 7 +#define CPPZMQ_VERSION_PATCH 1 + +#define CPPZMQ_VERSION \ + ZMQ_MAKE_VERSION(CPPZMQ_VERSION_MAJOR, CPPZMQ_VERSION_MINOR, \ + CPPZMQ_VERSION_PATCH) + +// Detect whether the compiler supports C++11 rvalue references. +#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 2)) \ + && defined(__GXX_EXPERIMENTAL_CXX0X__)) +#define ZMQ_HAS_RVALUE_REFS +#define ZMQ_DELETED_FUNCTION = delete +#elif defined(__clang__) +#if __has_feature(cxx_rvalue_references) +#define ZMQ_HAS_RVALUE_REFS +#endif + +#if __has_feature(cxx_deleted_functions) +#define ZMQ_DELETED_FUNCTION = delete +#else +#define ZMQ_DELETED_FUNCTION +#endif +#elif defined(_MSC_VER) && (_MSC_VER >= 1900) +#define ZMQ_HAS_RVALUE_REFS +#define ZMQ_DELETED_FUNCTION = delete +#elif defined(_MSC_VER) && (_MSC_VER >= 1600) +#define ZMQ_HAS_RVALUE_REFS +#define ZMQ_DELETED_FUNCTION +#else +#define ZMQ_DELETED_FUNCTION +#endif + +#if defined(ZMQ_CPP11) && !defined(__llvm__) && !defined(__INTEL_COMPILER) \ + && defined(__GNUC__) && __GNUC__ < 5 +#define ZMQ_CPP11_PARTIAL +#elif defined(__GLIBCXX__) && __GLIBCXX__ < 20160805 +//the date here is the last date of gcc 4.9.4, which +// effectively means libstdc++ from gcc 5.5 and higher won't trigger this branch +#define ZMQ_CPP11_PARTIAL +#endif + +#ifdef ZMQ_CPP11 +#ifdef ZMQ_CPP11_PARTIAL +#define ZMQ_IS_TRIVIALLY_COPYABLE(T) __has_trivial_copy(T) +#else +#include +#define ZMQ_IS_TRIVIALLY_COPYABLE(T) std::is_trivially_copyable::value +#endif +#endif + +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 3, 0) +#define ZMQ_NEW_MONITOR_EVENT_LAYOUT +#endif + +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0) +#define ZMQ_HAS_PROXY_STEERABLE +/* Socket event data */ +typedef struct +{ + uint16_t event; // id of the event as bitfield + int32_t value; // value is either error code, fd or reconnect interval +} zmq_event_t; +#endif + +// Avoid using deprecated message receive function when possible +#if ZMQ_VERSION < ZMQ_MAKE_VERSION(3, 2, 0) +#define zmq_msg_recv(msg, socket, flags) zmq_recvmsg(socket, msg, flags) +#endif + + +// In order to prevent unused variable warnings when building in non-debug +// mode use this macro to make assertions. +#ifndef NDEBUG +#define ZMQ_ASSERT(expression) assert(expression) +#else +#define ZMQ_ASSERT(expression) (void) (expression) +#endif + +namespace zmq +{ +#ifdef ZMQ_CPP11 +namespace detail +{ +namespace ranges +{ +using std::begin; +using std::end; +template auto begin(T &&r) -> decltype(begin(std::forward(r))) +{ + return begin(std::forward(r)); +} +template auto end(T &&r) -> decltype(end(std::forward(r))) +{ + return end(std::forward(r)); +} +} // namespace ranges + +template using void_t = void; + +template +using iter_value_t = typename std::iterator_traits::value_type; + +template +using range_iter_t = decltype( + ranges::begin(std::declval::type &>())); + +template using range_value_t = iter_value_t>; + +template struct is_range : std::false_type +{ +}; + +template +struct is_range< + T, + void_t::type &>()) + == ranges::end(std::declval::type &>()))>> + : std::true_type +{ +}; + +} // namespace detail +#endif + +typedef zmq_free_fn free_fn; +typedef zmq_pollitem_t pollitem_t; + +class error_t : public std::exception +{ + public: + error_t() ZMQ_NOTHROW : errnum(zmq_errno()) {} + explicit error_t(int err) ZMQ_NOTHROW : errnum(err) {} + virtual const char *what() const ZMQ_NOTHROW ZMQ_OVERRIDE + { + return zmq_strerror(errnum); + } + int num() const ZMQ_NOTHROW { return errnum; } + + private: + int errnum; +}; + +inline int poll(zmq_pollitem_t *items_, size_t nitems_, long timeout_ = -1) +{ + int rc = zmq_poll(items_, static_cast(nitems_), timeout_); + if (rc < 0) + throw error_t(); + return rc; +} + +ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items") +inline int poll(zmq_pollitem_t const *items_, size_t nitems_, long timeout_ = -1) +{ + return poll(const_cast(items_), nitems_, timeout_); +} + +#ifdef ZMQ_CPP11 +ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items") +inline int +poll(zmq_pollitem_t const *items, size_t nitems, std::chrono::milliseconds timeout) +{ + return poll(const_cast(items), nitems, + static_cast(timeout.count())); +} + +ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items") +inline int poll(std::vector const &items, + std::chrono::milliseconds timeout) +{ + return poll(const_cast(items.data()), items.size(), + static_cast(timeout.count())); +} + +ZMQ_DEPRECATED("from 4.3.1, use poll taking non-const items") +inline int poll(std::vector const &items, long timeout_ = -1) +{ + return poll(const_cast(items.data()), items.size(), timeout_); +} + +inline int +poll(zmq_pollitem_t *items, size_t nitems, std::chrono::milliseconds timeout) +{ + return poll(items, nitems, static_cast(timeout.count())); +} + +inline int poll(std::vector &items, + std::chrono::milliseconds timeout) +{ + return poll(items.data(), items.size(), static_cast(timeout.count())); +} + +ZMQ_DEPRECATED("from 4.3.1, use poll taking std::chrono instead of long") +inline int poll(std::vector &items, long timeout_ = -1) +{ + return poll(items.data(), items.size(), timeout_); +} + +template +inline int poll(std::array &items, + std::chrono::milliseconds timeout) +{ + return poll(items.data(), items.size(), static_cast(timeout.count())); +} +#endif + + +inline void version(int *major_, int *minor_, int *patch_) +{ + zmq_version(major_, minor_, patch_); +} + +#ifdef ZMQ_CPP11 +inline std::tuple version() +{ + std::tuple v; + zmq_version(&std::get<0>(v), &std::get<1>(v), &std::get<2>(v)); + return v; +} + +#if !defined(ZMQ_CPP11_PARTIAL) +namespace detail +{ +template struct is_char_type +{ + // true if character type for string literals in C++11 + static constexpr bool value = + std::is_same::value || std::is_same::value + || std::is_same::value || std::is_same::value; +}; +} +#endif + +#endif + +class message_t +{ + public: + message_t() ZMQ_NOTHROW + { + int rc = zmq_msg_init(&msg); + ZMQ_ASSERT(rc == 0); + } + + explicit message_t(size_t size_) + { + int rc = zmq_msg_init_size(&msg, size_); + if (rc != 0) + throw error_t(); + } + + template message_t(ForwardIter first, ForwardIter last) + { + typedef typename std::iterator_traits::value_type value_t; + + assert(std::distance(first, last) >= 0); + size_t const size_ = + static_cast(std::distance(first, last)) * sizeof(value_t); + int const rc = zmq_msg_init_size(&msg, size_); + if (rc != 0) + throw error_t(); + std::copy(first, last, data()); + } + + message_t(const void *data_, size_t size_) + { + int rc = zmq_msg_init_size(&msg, size_); + if (rc != 0) + throw error_t(); + if (size_) { + // this constructor allows (nullptr, 0), + // memcpy with a null pointer is UB + memcpy(data(), data_, size_); + } + } + + message_t(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR) + { + int rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_); + if (rc != 0) + throw error_t(); + } + + // overload set of string-like types and generic containers +#if defined(ZMQ_CPP11) && !defined(ZMQ_CPP11_PARTIAL) + // NOTE this constructor will include the null terminator + // when called with a string literal. + // An overload taking const char* can not be added because + // it would be preferred over this function and break compatiblity. + template< + class Char, + size_t N, + typename = typename std::enable_if::value>::type> + ZMQ_DEPRECATED("from 4.7.0, use constructors taking iterators, (pointer, size) " + "or strings instead") + explicit message_t(const Char (&data)[N]) : + message_t(detail::ranges::begin(data), detail::ranges::end(data)) + { + } + + template::value + && ZMQ_IS_TRIVIALLY_COPYABLE(detail::range_value_t) + && !detail::is_char_type>::value + && !std::is_same::value>::type> + explicit message_t(const Range &rng) : + message_t(detail::ranges::begin(rng), detail::ranges::end(rng)) + { + } + + explicit message_t(const std::string &str) : message_t(str.data(), str.size()) {} + +#if CPPZMQ_HAS_STRING_VIEW + explicit message_t(std::string_view str) : message_t(str.data(), str.size()) {} +#endif + +#endif + +#ifdef ZMQ_HAS_RVALUE_REFS + message_t(message_t &&rhs) ZMQ_NOTHROW : msg(rhs.msg) + { + int rc = zmq_msg_init(&rhs.msg); + ZMQ_ASSERT(rc == 0); + } + + message_t &operator=(message_t &&rhs) ZMQ_NOTHROW + { + std::swap(msg, rhs.msg); + return *this; + } +#endif + + ~message_t() ZMQ_NOTHROW + { + int rc = zmq_msg_close(&msg); + ZMQ_ASSERT(rc == 0); + } + + void rebuild() + { + int rc = zmq_msg_close(&msg); + if (rc != 0) + throw error_t(); + rc = zmq_msg_init(&msg); + ZMQ_ASSERT(rc == 0); + } + + void rebuild(size_t size_) + { + int rc = zmq_msg_close(&msg); + if (rc != 0) + throw error_t(); + rc = zmq_msg_init_size(&msg, size_); + if (rc != 0) + throw error_t(); + } + + void rebuild(const void *data_, size_t size_) + { + int rc = zmq_msg_close(&msg); + if (rc != 0) + throw error_t(); + rc = zmq_msg_init_size(&msg, size_); + if (rc != 0) + throw error_t(); + memcpy(data(), data_, size_); + } + + void rebuild(void *data_, size_t size_, free_fn *ffn_, void *hint_ = ZMQ_NULLPTR) + { + int rc = zmq_msg_close(&msg); + if (rc != 0) + throw error_t(); + rc = zmq_msg_init_data(&msg, data_, size_, ffn_, hint_); + if (rc != 0) + throw error_t(); + } + + ZMQ_DEPRECATED("from 4.3.1, use move taking non-const reference instead") + void move(message_t const *msg_) + { + int rc = zmq_msg_move(&msg, const_cast(msg_->handle())); + if (rc != 0) + throw error_t(); + } + + void move(message_t &msg_) + { + int rc = zmq_msg_move(&msg, msg_.handle()); + if (rc != 0) + throw error_t(); + } + + ZMQ_DEPRECATED("from 4.3.1, use copy taking non-const reference instead") + void copy(message_t const *msg_) + { + int rc = zmq_msg_copy(&msg, const_cast(msg_->handle())); + if (rc != 0) + throw error_t(); + } + + void copy(message_t &msg_) + { + int rc = zmq_msg_copy(&msg, msg_.handle()); + if (rc != 0) + throw error_t(); + } + + bool more() const ZMQ_NOTHROW + { + int rc = zmq_msg_more(const_cast(&msg)); + return rc != 0; + } + + void *data() ZMQ_NOTHROW { return zmq_msg_data(&msg); } + + const void *data() const ZMQ_NOTHROW + { + return zmq_msg_data(const_cast(&msg)); + } + + size_t size() const ZMQ_NOTHROW + { + return zmq_msg_size(const_cast(&msg)); + } + + ZMQ_NODISCARD bool empty() const ZMQ_NOTHROW { return size() == 0u; } + + template T *data() ZMQ_NOTHROW { return static_cast(data()); } + + template T const *data() const ZMQ_NOTHROW + { + return static_cast(data()); + } + + ZMQ_DEPRECATED("from 4.3.0, use operator== instead") + bool equal(const message_t *other) const ZMQ_NOTHROW { return *this == *other; } + + bool operator==(const message_t &other) const ZMQ_NOTHROW + { + const size_t my_size = size(); + return my_size == other.size() && 0 == memcmp(data(), other.data(), my_size); + } + + bool operator!=(const message_t &other) const ZMQ_NOTHROW + { + return !(*this == other); + } + +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3, 2, 0) + int get(int property_) + { + int value = zmq_msg_get(&msg, property_); + if (value == -1) + throw error_t(); + return value; + } +#endif + +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0) + const char *gets(const char *property_) + { + const char *value = zmq_msg_gets(&msg, property_); + if (value == ZMQ_NULLPTR) + throw error_t(); + return value; + } +#endif + +#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0) + uint32_t routing_id() const + { + return zmq_msg_routing_id(const_cast(&msg)); + } + + void set_routing_id(uint32_t routing_id) + { + int rc = zmq_msg_set_routing_id(&msg, routing_id); + if (rc != 0) + throw error_t(); + } + + const char *group() const + { + return zmq_msg_group(const_cast(&msg)); + } + + void set_group(const char *group) + { + int rc = zmq_msg_set_group(&msg, group); + if (rc != 0) + throw error_t(); + } +#endif + + // interpret message content as a string + std::string to_string() const + { + return std::string(static_cast(data()), size()); + } +#if CPPZMQ_HAS_STRING_VIEW + // interpret message content as a string + std::string_view to_string_view() const noexcept + { + return std::string_view(static_cast(data()), size()); + } +#endif + + /** Dump content to string for debugging. + * Ascii chars are readable, the rest is printed as hex. + * Probably ridiculously slow. + * Use to_string() or to_string_view() for + * interpreting the message as a string. + */ + std::string str() const + { + // Partly mutuated from the same method in zmq::multipart_t + std::stringstream os; + + const unsigned char *msg_data = this->data(); + unsigned char byte; + size_t size = this->size(); + int is_ascii[2] = {0, 0}; + + os << "zmq::message_t [size " << std::dec << std::setw(3) + << std::setfill('0') << size << "] ("; + // Totally arbitrary + if (size >= 1000) { + os << "... too big to print)"; + } else { + while (size--) { + byte = *msg_data++; + + is_ascii[1] = (byte >= 32 && byte < 127); + if (is_ascii[1] != is_ascii[0]) + os << " "; // Separate text/non text + + if (is_ascii[1]) { + os << byte; + } else { + os << std::hex << std::uppercase << std::setw(2) + << std::setfill('0') << static_cast(byte); + } + is_ascii[0] = is_ascii[1]; + } + os << ")"; + } + return os.str(); + } + + void swap(message_t &other) ZMQ_NOTHROW + { + // this assumes zmq::msg_t from libzmq is trivially relocatable + std::swap(msg, other.msg); + } + + ZMQ_NODISCARD zmq_msg_t *handle() ZMQ_NOTHROW { return &msg; } + ZMQ_NODISCARD const zmq_msg_t *handle() const ZMQ_NOTHROW { return &msg; } + + private: + // The underlying message + zmq_msg_t msg; + + // Disable implicit message copying, so that users won't use shared + // messages (less efficient) without being aware of the fact. + message_t(const message_t &) ZMQ_DELETED_FUNCTION; + void operator=(const message_t &) ZMQ_DELETED_FUNCTION; +}; + +inline void swap(message_t &a, message_t &b) ZMQ_NOTHROW +{ + a.swap(b); +} + +#ifdef ZMQ_CPP11 +enum class ctxopt +{ +#ifdef ZMQ_BLOCKY + blocky = ZMQ_BLOCKY, +#endif +#ifdef ZMQ_IO_THREADS + io_threads = ZMQ_IO_THREADS, +#endif +#ifdef ZMQ_THREAD_SCHED_POLICY + thread_sched_policy = ZMQ_THREAD_SCHED_POLICY, +#endif +#ifdef ZMQ_THREAD_PRIORITY + thread_priority = ZMQ_THREAD_PRIORITY, +#endif +#ifdef ZMQ_THREAD_AFFINITY_CPU_ADD + thread_affinity_cpu_add = ZMQ_THREAD_AFFINITY_CPU_ADD, +#endif +#ifdef ZMQ_THREAD_AFFINITY_CPU_REMOVE + thread_affinity_cpu_remove = ZMQ_THREAD_AFFINITY_CPU_REMOVE, +#endif +#ifdef ZMQ_THREAD_NAME_PREFIX + thread_name_prefix = ZMQ_THREAD_NAME_PREFIX, +#endif +#ifdef ZMQ_MAX_MSGSZ + max_msgsz = ZMQ_MAX_MSGSZ, +#endif +#ifdef ZMQ_ZERO_COPY_RECV + zero_copy_recv = ZMQ_ZERO_COPY_RECV, +#endif +#ifdef ZMQ_MAX_SOCKETS + max_sockets = ZMQ_MAX_SOCKETS, +#endif +#ifdef ZMQ_SOCKET_LIMIT + socket_limit = ZMQ_SOCKET_LIMIT, +#endif +#ifdef ZMQ_IPV6 + ipv6 = ZMQ_IPV6, +#endif +#ifdef ZMQ_MSG_T_SIZE + msg_t_size = ZMQ_MSG_T_SIZE +#endif +}; +#endif + +class context_t +{ + public: + context_t() + { + ptr = zmq_ctx_new(); + if (ptr == ZMQ_NULLPTR) + throw error_t(); + } + + + explicit context_t(int io_threads_, int max_sockets_ = ZMQ_MAX_SOCKETS_DFLT) + { + ptr = zmq_ctx_new(); + if (ptr == ZMQ_NULLPTR) + throw error_t(); + + int rc = zmq_ctx_set(ptr, ZMQ_IO_THREADS, io_threads_); + ZMQ_ASSERT(rc == 0); + + rc = zmq_ctx_set(ptr, ZMQ_MAX_SOCKETS, max_sockets_); + ZMQ_ASSERT(rc == 0); + } + +#ifdef ZMQ_HAS_RVALUE_REFS + context_t(context_t &&rhs) ZMQ_NOTHROW : ptr(rhs.ptr) { rhs.ptr = ZMQ_NULLPTR; } + context_t &operator=(context_t &&rhs) ZMQ_NOTHROW + { + close(); + std::swap(ptr, rhs.ptr); + return *this; + } +#endif + + ~context_t() ZMQ_NOTHROW { close(); } + + ZMQ_CPP11_DEPRECATED("from 4.7.0, use set taking zmq::ctxopt instead") + int setctxopt(int option_, int optval_) + { + int rc = zmq_ctx_set(ptr, option_, optval_); + ZMQ_ASSERT(rc == 0); + return rc; + } + + ZMQ_CPP11_DEPRECATED("from 4.7.0, use get taking zmq::ctxopt instead") + int getctxopt(int option_) { return zmq_ctx_get(ptr, option_); } + +#ifdef ZMQ_CPP11 + void set(ctxopt option, int optval) + { + int rc = zmq_ctx_set(ptr, static_cast(option), optval); + if (rc == -1) + throw error_t(); + } + + ZMQ_NODISCARD int get(ctxopt option) + { + int rc = zmq_ctx_get(ptr, static_cast(option)); + // some options have a default value of -1 + // which is unfortunate, and may result in errors + // that don't make sense + if (rc == -1) + throw error_t(); + return rc; + } +#endif + + // Terminates context (see also shutdown()). + void close() ZMQ_NOTHROW + { + if (ptr == ZMQ_NULLPTR) + return; + + int rc; + do { + rc = zmq_ctx_destroy(ptr); + } while (rc == -1 && errno == EINTR); + + ZMQ_ASSERT(rc == 0); + ptr = ZMQ_NULLPTR; + } + + // Shutdown context in preparation for termination (close()). + // Causes all blocking socket operations and any further + // socket operations to return with ETERM. + void shutdown() ZMQ_NOTHROW + { + if (ptr == ZMQ_NULLPTR) + return; + int rc = zmq_ctx_shutdown(ptr); + ZMQ_ASSERT(rc == 0); + } + + // Be careful with this, it's probably only useful for + // using the C api together with an existing C++ api. + // Normally you should never need to use this. + ZMQ_EXPLICIT operator void *() ZMQ_NOTHROW { return ptr; } + + ZMQ_EXPLICIT operator void const *() const ZMQ_NOTHROW { return ptr; } + + ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return ptr; } + + ZMQ_DEPRECATED("from 4.7.0, use handle() != nullptr instead") + operator bool() const ZMQ_NOTHROW { return ptr != ZMQ_NULLPTR; } + + void swap(context_t &other) ZMQ_NOTHROW { std::swap(ptr, other.ptr); } + + private: + void *ptr; + + context_t(const context_t &) ZMQ_DELETED_FUNCTION; + void operator=(const context_t &) ZMQ_DELETED_FUNCTION; +}; + +inline void swap(context_t &a, context_t &b) ZMQ_NOTHROW +{ + a.swap(b); +} + +#ifdef ZMQ_CPP11 + +struct recv_buffer_size +{ + size_t size; // number of bytes written to buffer + size_t untruncated_size; // untruncated message size in bytes + + ZMQ_NODISCARD bool truncated() const noexcept + { + return size != untruncated_size; + } +}; + +#if CPPZMQ_HAS_OPTIONAL + +using send_result_t = std::optional; +using recv_result_t = std::optional; +using recv_buffer_result_t = std::optional; + +#else + +namespace detail +{ +// A C++11 type emulating the most basic +// operations of std::optional for trivial types +template class trivial_optional +{ + public: + static_assert(std::is_trivial::value, "T must be trivial"); + using value_type = T; + + trivial_optional() = default; + trivial_optional(T value) noexcept : _value(value), _has_value(true) {} + + const T *operator->() const noexcept + { + assert(_has_value); + return &_value; + } + T *operator->() noexcept + { + assert(_has_value); + return &_value; + } + + const T &operator*() const noexcept + { + assert(_has_value); + return _value; + } + T &operator*() noexcept + { + assert(_has_value); + return _value; + } + + T &value() + { + if (!_has_value) + throw std::exception(); + return _value; + } + const T &value() const + { + if (!_has_value) + throw std::exception(); + return _value; + } + + explicit operator bool() const noexcept { return _has_value; } + bool has_value() const noexcept { return _has_value; } + + private: + T _value{}; + bool _has_value{false}; +}; +} // namespace detail + +using send_result_t = detail::trivial_optional; +using recv_result_t = detail::trivial_optional; +using recv_buffer_result_t = detail::trivial_optional; + +#endif + +namespace detail +{ +template constexpr T enum_bit_or(T a, T b) noexcept +{ + static_assert(std::is_enum::value, "must be enum"); + using U = typename std::underlying_type::type; + return static_cast(static_cast(a) | static_cast(b)); +} +template constexpr T enum_bit_and(T a, T b) noexcept +{ + static_assert(std::is_enum::value, "must be enum"); + using U = typename std::underlying_type::type; + return static_cast(static_cast(a) & static_cast(b)); +} +template constexpr T enum_bit_xor(T a, T b) noexcept +{ + static_assert(std::is_enum::value, "must be enum"); + using U = typename std::underlying_type::type; + return static_cast(static_cast(a) ^ static_cast(b)); +} +template constexpr T enum_bit_not(T a) noexcept +{ + static_assert(std::is_enum::value, "must be enum"); + using U = typename std::underlying_type::type; + return static_cast(~static_cast(a)); +} +} // namespace detail + +// partially satisfies named requirement BitmaskType +enum class send_flags : int +{ + none = 0, + dontwait = ZMQ_DONTWAIT, + sndmore = ZMQ_SNDMORE +}; + +constexpr send_flags operator|(send_flags a, send_flags b) noexcept +{ + return detail::enum_bit_or(a, b); +} +constexpr send_flags operator&(send_flags a, send_flags b) noexcept +{ + return detail::enum_bit_and(a, b); +} +constexpr send_flags operator^(send_flags a, send_flags b) noexcept +{ + return detail::enum_bit_xor(a, b); +} +constexpr send_flags operator~(send_flags a) noexcept +{ + return detail::enum_bit_not(a); +} + +// partially satisfies named requirement BitmaskType +enum class recv_flags : int +{ + none = 0, + dontwait = ZMQ_DONTWAIT +}; + +constexpr recv_flags operator|(recv_flags a, recv_flags b) noexcept +{ + return detail::enum_bit_or(a, b); +} +constexpr recv_flags operator&(recv_flags a, recv_flags b) noexcept +{ + return detail::enum_bit_and(a, b); +} +constexpr recv_flags operator^(recv_flags a, recv_flags b) noexcept +{ + return detail::enum_bit_xor(a, b); +} +constexpr recv_flags operator~(recv_flags a) noexcept +{ + return detail::enum_bit_not(a); +} + + +// mutable_buffer, const_buffer and buffer are based on +// the Networking TS specification, draft: +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4771.pdf + +class mutable_buffer +{ + public: + constexpr mutable_buffer() noexcept : _data(nullptr), _size(0) {} + constexpr mutable_buffer(void *p, size_t n) noexcept : _data(p), _size(n) + { +#ifdef ZMQ_EXTENDED_CONSTEXPR + assert(p != nullptr || n == 0); +#endif + } + + constexpr void *data() const noexcept { return _data; } + constexpr size_t size() const noexcept { return _size; } + mutable_buffer &operator+=(size_t n) noexcept + { + // (std::min) is a workaround for when a min macro is defined + const auto shift = (std::min)(n, _size); + _data = static_cast(_data) + shift; + _size -= shift; + return *this; + } + + private: + void *_data; + size_t _size; +}; + +inline mutable_buffer operator+(const mutable_buffer &mb, size_t n) noexcept +{ + return mutable_buffer(static_cast(mb.data()) + (std::min)(n, mb.size()), + mb.size() - (std::min)(n, mb.size())); +} +inline mutable_buffer operator+(size_t n, const mutable_buffer &mb) noexcept +{ + return mb + n; +} + +class const_buffer +{ + public: + constexpr const_buffer() noexcept : _data(nullptr), _size(0) {} + constexpr const_buffer(const void *p, size_t n) noexcept : _data(p), _size(n) + { +#ifdef ZMQ_EXTENDED_CONSTEXPR + assert(p != nullptr || n == 0); +#endif + } + constexpr const_buffer(const mutable_buffer &mb) noexcept : + _data(mb.data()), + _size(mb.size()) + { + } + + constexpr const void *data() const noexcept { return _data; } + constexpr size_t size() const noexcept { return _size; } + const_buffer &operator+=(size_t n) noexcept + { + const auto shift = (std::min)(n, _size); + _data = static_cast(_data) + shift; + _size -= shift; + return *this; + } + + private: + const void *_data; + size_t _size; +}; + +inline const_buffer operator+(const const_buffer &cb, size_t n) noexcept +{ + return const_buffer(static_cast(cb.data()) + + (std::min)(n, cb.size()), + cb.size() - (std::min)(n, cb.size())); +} +inline const_buffer operator+(size_t n, const const_buffer &cb) noexcept +{ + return cb + n; +} + +// buffer creation + +constexpr mutable_buffer buffer(void *p, size_t n) noexcept +{ + return mutable_buffer(p, n); +} +constexpr const_buffer buffer(const void *p, size_t n) noexcept +{ + return const_buffer(p, n); +} +constexpr mutable_buffer buffer(const mutable_buffer &mb) noexcept +{ + return mb; +} +inline mutable_buffer buffer(const mutable_buffer &mb, size_t n) noexcept +{ + return mutable_buffer(mb.data(), (std::min)(mb.size(), n)); +} +constexpr const_buffer buffer(const const_buffer &cb) noexcept +{ + return cb; +} +inline const_buffer buffer(const const_buffer &cb, size_t n) noexcept +{ + return const_buffer(cb.data(), (std::min)(cb.size(), n)); +} + +namespace detail +{ +template struct is_buffer +{ + static constexpr bool value = + std::is_same::value || std::is_same::value; +}; + +template struct is_pod_like +{ + // NOTE: The networking draft N4771 section 16.11 requires + // T in the buffer functions below to be + // trivially copyable OR standard layout. + // Here we decide to be conservative and require both. + static constexpr bool value = + ZMQ_IS_TRIVIALLY_COPYABLE(T) && std::is_standard_layout::value; +}; + +template constexpr auto seq_size(const C &c) noexcept -> decltype(c.size()) +{ + return c.size(); +} +template +constexpr size_t seq_size(const T (&/*array*/)[N]) noexcept +{ + return N; +} + +template +auto buffer_contiguous_sequence(Seq &&seq) noexcept + -> decltype(buffer(std::addressof(*std::begin(seq)), size_t{})) +{ + using T = typename std::remove_cv< + typename std::remove_reference::type>::type; + static_assert(detail::is_pod_like::value, "T must be POD"); + + const auto size = seq_size(seq); + return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr, + size * sizeof(T)); +} +template +auto buffer_contiguous_sequence(Seq &&seq, size_t n_bytes) noexcept + -> decltype(buffer_contiguous_sequence(seq)) +{ + using T = typename std::remove_cv< + typename std::remove_reference::type>::type; + static_assert(detail::is_pod_like::value, "T must be POD"); + + const auto size = seq_size(seq); + return buffer(size != 0u ? std::addressof(*std::begin(seq)) : nullptr, + (std::min)(size * sizeof(T), n_bytes)); +} + +} // namespace detail + +// C array +template mutable_buffer buffer(T (&data)[N]) noexcept +{ + return detail::buffer_contiguous_sequence(data); +} +template +mutable_buffer buffer(T (&data)[N], size_t n_bytes) noexcept +{ + return detail::buffer_contiguous_sequence(data, n_bytes); +} +template const_buffer buffer(const T (&data)[N]) noexcept +{ + return detail::buffer_contiguous_sequence(data); +} +template +const_buffer buffer(const T (&data)[N], size_t n_bytes) noexcept +{ + return detail::buffer_contiguous_sequence(data, n_bytes); +} +// std::array +template mutable_buffer buffer(std::array &data) noexcept +{ + return detail::buffer_contiguous_sequence(data); +} +template +mutable_buffer buffer(std::array &data, size_t n_bytes) noexcept +{ + return detail::buffer_contiguous_sequence(data, n_bytes); +} +template +const_buffer buffer(std::array &data) noexcept +{ + return detail::buffer_contiguous_sequence(data); +} +template +const_buffer buffer(std::array &data, size_t n_bytes) noexcept +{ + return detail::buffer_contiguous_sequence(data, n_bytes); +} +template +const_buffer buffer(const std::array &data) noexcept +{ + return detail::buffer_contiguous_sequence(data); +} +template +const_buffer buffer(const std::array &data, size_t n_bytes) noexcept +{ + return detail::buffer_contiguous_sequence(data, n_bytes); +} +// std::vector +template +mutable_buffer buffer(std::vector &data) noexcept +{ + return detail::buffer_contiguous_sequence(data); +} +template +mutable_buffer buffer(std::vector &data, size_t n_bytes) noexcept +{ + return detail::buffer_contiguous_sequence(data, n_bytes); +} +template +const_buffer buffer(const std::vector &data) noexcept +{ + return detail::buffer_contiguous_sequence(data); +} +template +const_buffer buffer(const std::vector &data, size_t n_bytes) noexcept +{ + return detail::buffer_contiguous_sequence(data, n_bytes); +} +// std::basic_string +template +mutable_buffer buffer(std::basic_string &data) noexcept +{ + return detail::buffer_contiguous_sequence(data); +} +template +mutable_buffer buffer(std::basic_string &data, + size_t n_bytes) noexcept +{ + return detail::buffer_contiguous_sequence(data, n_bytes); +} +template +const_buffer buffer(const std::basic_string &data) noexcept +{ + return detail::buffer_contiguous_sequence(data); +} +template +const_buffer buffer(const std::basic_string &data, + size_t n_bytes) noexcept +{ + return detail::buffer_contiguous_sequence(data, n_bytes); +} + +#if CPPZMQ_HAS_STRING_VIEW +// std::basic_string_view +template +const_buffer buffer(std::basic_string_view data) noexcept +{ + return detail::buffer_contiguous_sequence(data); +} +template +const_buffer buffer(std::basic_string_view data, size_t n_bytes) noexcept +{ + return detail::buffer_contiguous_sequence(data, n_bytes); +} +#endif + +// Buffer for a string literal (null terminated) +// where the buffer size excludes the terminating character. +// Equivalent to zmq::buffer(std::string_view("...")). +template +constexpr const_buffer str_buffer(const Char (&data)[N]) noexcept +{ + static_assert(detail::is_pod_like::value, "Char must be POD"); +#ifdef ZMQ_EXTENDED_CONSTEXPR + assert(data[N - 1] == Char{0}); +#endif + return const_buffer(static_cast(data), (N - 1) * sizeof(Char)); +} + +namespace literals +{ +constexpr const_buffer operator"" _zbuf(const char *str, size_t len) noexcept +{ + return const_buffer(str, len * sizeof(char)); +} +constexpr const_buffer operator"" _zbuf(const wchar_t *str, size_t len) noexcept +{ + return const_buffer(str, len * sizeof(wchar_t)); +} +constexpr const_buffer operator"" _zbuf(const char16_t *str, size_t len) noexcept +{ + return const_buffer(str, len * sizeof(char16_t)); +} +constexpr const_buffer operator"" _zbuf(const char32_t *str, size_t len) noexcept +{ + return const_buffer(str, len * sizeof(char32_t)); +} +} + +#endif // ZMQ_CPP11 + + +#ifdef ZMQ_CPP11 +namespace sockopt +{ +// There are two types of options, +// integral type with known compiler time size (int, bool, int64_t, uint64_t) +// and arrays with dynamic size (strings, binary data). + +// BoolUnit: if true accepts values of type bool (but passed as T into libzmq) +template struct integral_option +{ +}; + +// NullTerm: +// 0: binary data +// 1: null-terminated string (`getsockopt` size includes null) +// 2: binary (size 32) or Z85 encoder string of size 41 (null included) +template struct array_option +{ +}; + +#define ZMQ_DEFINE_INTEGRAL_OPT(OPT, NAME, TYPE) \ + using NAME##_t = integral_option; \ + ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {} +#define ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(OPT, NAME, TYPE) \ + using NAME##_t = integral_option; \ + ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {} +#define ZMQ_DEFINE_ARRAY_OPT(OPT, NAME) \ + using NAME##_t = array_option; \ + ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {} +#define ZMQ_DEFINE_ARRAY_OPT_BINARY(OPT, NAME) \ + using NAME##_t = array_option; \ + ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {} +#define ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(OPT, NAME) \ + using NAME##_t = array_option; \ + ZMQ_INLINE_VAR ZMQ_CONSTEXPR_VAR NAME##_t NAME {} + +// duplicate definition from libzmq 4.3.3 +#if defined _WIN32 +#if defined _WIN64 +typedef unsigned __int64 cppzmq_fd_t; +#else +typedef unsigned int cppzmq_fd_t; +#endif +#else +typedef int cppzmq_fd_t; +#endif + +#ifdef ZMQ_AFFINITY +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_AFFINITY, affinity, uint64_t); +#endif +#ifdef ZMQ_BACKLOG +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_BACKLOG, backlog, int); +#endif +#ifdef ZMQ_BINDTODEVICE +ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_BINDTODEVICE, bindtodevice); +#endif +#ifdef ZMQ_CONFLATE +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CONFLATE, conflate, int); +#endif +#ifdef ZMQ_CONNECT_ROUTING_ID +ZMQ_DEFINE_ARRAY_OPT(ZMQ_CONNECT_ROUTING_ID, connect_routing_id); +#endif +#ifdef ZMQ_CONNECT_TIMEOUT +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_CONNECT_TIMEOUT, connect_timeout, int); +#endif +#ifdef ZMQ_CURVE_PUBLICKEY +ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_PUBLICKEY, curve_publickey); +#endif +#ifdef ZMQ_CURVE_SECRETKEY +ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SECRETKEY, curve_secretkey); +#endif +#ifdef ZMQ_CURVE_SERVER +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_CURVE_SERVER, curve_server, int); +#endif +#ifdef ZMQ_CURVE_SERVERKEY +ZMQ_DEFINE_ARRAY_OPT_BIN_OR_Z85(ZMQ_CURVE_SERVERKEY, curve_serverkey); +#endif +#ifdef ZMQ_EVENTS +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_EVENTS, events, int); +#endif +#ifdef ZMQ_FD +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_FD, fd, cppzmq_fd_t); +#endif +#ifdef ZMQ_GSSAPI_PLAINTEXT +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_PLAINTEXT, gssapi_plaintext, int); +#endif +#ifdef ZMQ_GSSAPI_SERVER +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_GSSAPI_SERVER, gssapi_server, int); +#endif +#ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL +ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL, gssapi_service_principal); +#endif +#ifdef ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_SERVICE_PRINCIPAL_NAMETYPE, + gssapi_service_principal_nametype, + int); +#endif +#ifdef ZMQ_GSSAPI_PRINCIPAL +ZMQ_DEFINE_ARRAY_OPT(ZMQ_GSSAPI_PRINCIPAL, gssapi_principal); +#endif +#ifdef ZMQ_GSSAPI_PRINCIPAL_NAMETYPE +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_GSSAPI_PRINCIPAL_NAMETYPE, + gssapi_principal_nametype, + int); +#endif +#ifdef ZMQ_HANDSHAKE_IVL +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HANDSHAKE_IVL, handshake_ivl, int); +#endif +#ifdef ZMQ_HEARTBEAT_IVL +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_IVL, heartbeat_ivl, int); +#endif +#ifdef ZMQ_HEARTBEAT_TIMEOUT +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TIMEOUT, heartbeat_timeout, int); +#endif +#ifdef ZMQ_HEARTBEAT_TTL +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_HEARTBEAT_TTL, heartbeat_ttl, int); +#endif +#ifdef ZMQ_IMMEDIATE +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IMMEDIATE, immediate, int); +#endif +#ifdef ZMQ_INVERT_MATCHING +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_INVERT_MATCHING, invert_matching, int); +#endif +#ifdef ZMQ_IPV6 +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_IPV6, ipv6, int); +#endif +#ifdef ZMQ_LAST_ENDPOINT +ZMQ_DEFINE_ARRAY_OPT(ZMQ_LAST_ENDPOINT, last_endpoint); +#endif +#ifdef ZMQ_LINGER +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_LINGER, linger, int); +#endif +#ifdef ZMQ_MAXMSGSIZE +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MAXMSGSIZE, maxmsgsize, int64_t); +#endif +#ifdef ZMQ_MECHANISM +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MECHANISM, mechanism, int); +#endif +#ifdef ZMQ_METADATA +ZMQ_DEFINE_ARRAY_OPT(ZMQ_METADATA, metadata); +#endif +#ifdef ZMQ_MULTICAST_HOPS +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_HOPS, multicast_hops, int); +#endif +#ifdef ZMQ_MULTICAST_LOOP +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_MULTICAST_LOOP, multicast_loop, int); +#endif +#ifdef ZMQ_MULTICAST_MAXTPDU +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_MULTICAST_MAXTPDU, multicast_maxtpdu, int); +#endif +#ifdef ZMQ_PLAIN_SERVER +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PLAIN_SERVER, plain_server, int); +#endif +#ifdef ZMQ_PLAIN_PASSWORD +ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_PASSWORD, plain_password); +#endif +#ifdef ZMQ_PLAIN_USERNAME +ZMQ_DEFINE_ARRAY_OPT(ZMQ_PLAIN_USERNAME, plain_username); +#endif +#ifdef ZMQ_USE_FD +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_USE_FD, use_fd, int); +#endif +#ifdef ZMQ_PROBE_ROUTER +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_PROBE_ROUTER, probe_router, int); +#endif +#ifdef ZMQ_RATE +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RATE, rate, int); +#endif +#ifdef ZMQ_RCVBUF +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVBUF, rcvbuf, int); +#endif +#ifdef ZMQ_RCVHWM +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVHWM, rcvhwm, int); +#endif +#ifdef ZMQ_RCVMORE +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_RCVMORE, rcvmore, int); +#endif +#ifdef ZMQ_RCVTIMEO +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RCVTIMEO, rcvtimeo, int); +#endif +#ifdef ZMQ_RECONNECT_IVL +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL, reconnect_ivl, int); +#endif +#ifdef ZMQ_RECONNECT_IVL_MAX +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECONNECT_IVL_MAX, reconnect_ivl_max, int); +#endif +#ifdef ZMQ_RECOVERY_IVL +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_RECOVERY_IVL, recovery_ivl, int); +#endif +#ifdef ZMQ_REQ_CORRELATE +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_CORRELATE, req_correlate, int); +#endif +#ifdef ZMQ_REQ_RELAXED +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_REQ_RELAXED, req_relaxed, int); +#endif +#ifdef ZMQ_ROUTER_HANDOVER +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_HANDOVER, router_handover, int); +#endif +#ifdef ZMQ_ROUTER_MANDATORY +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ROUTER_MANDATORY, router_mandatory, int); +#endif +#ifdef ZMQ_ROUTER_NOTIFY +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_ROUTER_NOTIFY, router_notify, int); +#endif +#ifdef ZMQ_ROUTING_ID +ZMQ_DEFINE_ARRAY_OPT_BINARY(ZMQ_ROUTING_ID, routing_id); +#endif +#ifdef ZMQ_SNDBUF +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDBUF, sndbuf, int); +#endif +#ifdef ZMQ_SNDHWM +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDHWM, sndhwm, int); +#endif +#ifdef ZMQ_SNDTIMEO +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_SNDTIMEO, sndtimeo, int); +#endif +#ifdef ZMQ_SOCKS_PROXY +ZMQ_DEFINE_ARRAY_OPT(ZMQ_SOCKS_PROXY, socks_proxy); +#endif +#ifdef ZMQ_STREAM_NOTIFY +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_STREAM_NOTIFY, stream_notify, int); +#endif +#ifdef ZMQ_SUBSCRIBE +ZMQ_DEFINE_ARRAY_OPT(ZMQ_SUBSCRIBE, subscribe); +#endif +#ifdef ZMQ_TCP_KEEPALIVE +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE, tcp_keepalive, int); +#endif +#ifdef ZMQ_TCP_KEEPALIVE_CNT +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_CNT, tcp_keepalive_cnt, int); +#endif +#ifdef ZMQ_TCP_KEEPALIVE_IDLE +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_IDLE, tcp_keepalive_idle, int); +#endif +#ifdef ZMQ_TCP_KEEPALIVE_INTVL +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_KEEPALIVE_INTVL, tcp_keepalive_intvl, int); +#endif +#ifdef ZMQ_TCP_MAXRT +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TCP_MAXRT, tcp_maxrt, int); +#endif +#ifdef ZMQ_THREAD_SAFE +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_THREAD_SAFE, thread_safe, int); +#endif +#ifdef ZMQ_TOS +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TOS, tos, int); +#endif +#ifdef ZMQ_TYPE +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_TYPE, type, int); +#endif +#ifdef ZMQ_UNSUBSCRIBE +ZMQ_DEFINE_ARRAY_OPT(ZMQ_UNSUBSCRIBE, unsubscribe); +#endif +#ifdef ZMQ_VMCI_BUFFER_SIZE +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_SIZE, vmci_buffer_size, uint64_t); +#endif +#ifdef ZMQ_VMCI_BUFFER_MIN_SIZE +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MIN_SIZE, vmci_buffer_min_size, uint64_t); +#endif +#ifdef ZMQ_VMCI_BUFFER_MAX_SIZE +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_BUFFER_MAX_SIZE, vmci_buffer_max_size, uint64_t); +#endif +#ifdef ZMQ_VMCI_CONNECT_TIMEOUT +ZMQ_DEFINE_INTEGRAL_OPT(ZMQ_VMCI_CONNECT_TIMEOUT, vmci_connect_timeout, int); +#endif +#ifdef ZMQ_XPUB_VERBOSE +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSE, xpub_verbose, int); +#endif +#ifdef ZMQ_XPUB_VERBOSER +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_VERBOSER, xpub_verboser, int); +#endif +#ifdef ZMQ_XPUB_MANUAL +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_MANUAL, xpub_manual, int); +#endif +#ifdef ZMQ_XPUB_NODROP +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_XPUB_NODROP, xpub_nodrop, int); +#endif +#ifdef ZMQ_XPUB_WELCOME_MSG +ZMQ_DEFINE_ARRAY_OPT(ZMQ_XPUB_WELCOME_MSG, xpub_welcome_msg); +#endif +#ifdef ZMQ_ZAP_ENFORCE_DOMAIN +ZMQ_DEFINE_INTEGRAL_BOOL_UNIT_OPT(ZMQ_ZAP_ENFORCE_DOMAIN, zap_enforce_domain, int); +#endif +#ifdef ZMQ_ZAP_DOMAIN +ZMQ_DEFINE_ARRAY_OPT(ZMQ_ZAP_DOMAIN, zap_domain); +#endif + +} // namespace sockopt +#endif // ZMQ_CPP11 + + +namespace detail +{ +class socket_base +{ + public: + socket_base() ZMQ_NOTHROW : _handle(ZMQ_NULLPTR) {} + ZMQ_EXPLICIT socket_base(void *handle) ZMQ_NOTHROW : _handle(handle) {} + + template + ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt") + void setsockopt(int option_, T const &optval) + { + setsockopt(option_, &optval, sizeof(T)); + } + + ZMQ_CPP11_DEPRECATED("from 4.7.0, use `set` taking option from zmq::sockopt") + void setsockopt(int option_, const void *optval_, size_t optvallen_) + { + int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_); + if (rc != 0) + throw error_t(); + } + + ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt") + void getsockopt(int option_, void *optval_, size_t *optvallen_) const + { + int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_); + if (rc != 0) + throw error_t(); + } + + template + ZMQ_CPP11_DEPRECATED("from 4.7.0, use `get` taking option from zmq::sockopt") + T getsockopt(int option_) const + { + T optval; + size_t optlen = sizeof(T); + getsockopt(option_, &optval, &optlen); + return optval; + } + +#ifdef ZMQ_CPP11 + // Set integral socket option, e.g. + // `socket.set(zmq::sockopt::linger, 0)` + template + void set(sockopt::integral_option, const T &val) + { + static_assert(std::is_integral::value, "T must be integral"); + set_option(Opt, &val, sizeof val); + } + + // Set integral socket option from boolean, e.g. + // `socket.set(zmq::sockopt::immediate, false)` + template + void set(sockopt::integral_option, bool val) + { + static_assert(std::is_integral::value, "T must be integral"); + T rep_val = val; + set_option(Opt, &rep_val, sizeof rep_val); + } + + // Set array socket option, e.g. + // `socket.set(zmq::sockopt::plain_username, "foo123")` + template + void set(sockopt::array_option, const char *buf) + { + set_option(Opt, buf, std::strlen(buf)); + } + + // Set array socket option, e.g. + // `socket.set(zmq::sockopt::routing_id, zmq::buffer(id))` + template + void set(sockopt::array_option, const_buffer buf) + { + set_option(Opt, buf.data(), buf.size()); + } + + // Set array socket option, e.g. + // `socket.set(zmq::sockopt::routing_id, id_str)` + template + void set(sockopt::array_option, const std::string &buf) + { + set_option(Opt, buf.data(), buf.size()); + } + +#if CPPZMQ_HAS_STRING_VIEW + // Set array socket option, e.g. + // `socket.set(zmq::sockopt::routing_id, id_str)` + template + void set(sockopt::array_option, std::string_view buf) + { + set_option(Opt, buf.data(), buf.size()); + } +#endif + + // Get scalar socket option, e.g. + // `auto opt = socket.get(zmq::sockopt::linger)` + template + ZMQ_NODISCARD T get(sockopt::integral_option) const + { + static_assert(std::is_integral::value, "T must be integral"); + T val; + size_t size = sizeof val; + get_option(Opt, &val, &size); + assert(size == sizeof val); + return val; + } + + // Get array socket option, writes to buf, returns option size in bytes, e.g. + // `size_t optsize = socket.get(zmq::sockopt::routing_id, zmq::buffer(id))` + template + ZMQ_NODISCARD size_t get(sockopt::array_option, + mutable_buffer buf) const + { + size_t size = buf.size(); + get_option(Opt, buf.data(), &size); + return size; + } + + // Get array socket option as string (initializes the string buffer size to init_size) e.g. + // `auto s = socket.get(zmq::sockopt::routing_id)` + // Note: removes the null character from null-terminated string options, + // i.e. the string size excludes the null character. + template + ZMQ_NODISCARD std::string get(sockopt::array_option, + size_t init_size = 1024) const + { + if (NullTerm == 2 && init_size == 1024) { + init_size = 41; // get as Z85 string + } + std::string str(init_size, '\0'); + size_t size = get(sockopt::array_option{}, buffer(str)); + if (NullTerm == 1) { + if (size > 0) { + assert(str[size - 1] == '\0'); + --size; + } + } else if (NullTerm == 2) { + assert(size == 32 || size == 41); + if (size == 41) { + assert(str[size - 1] == '\0'); + --size; + } + } + str.resize(size); + return str; + } +#endif + + void bind(std::string const &addr) { bind(addr.c_str()); } + + void bind(const char *addr_) + { + int rc = zmq_bind(_handle, addr_); + if (rc != 0) + throw error_t(); + } + + void unbind(std::string const &addr) { unbind(addr.c_str()); } + + void unbind(const char *addr_) + { + int rc = zmq_unbind(_handle, addr_); + if (rc != 0) + throw error_t(); + } + + void connect(std::string const &addr) { connect(addr.c_str()); } + + void connect(const char *addr_) + { + int rc = zmq_connect(_handle, addr_); + if (rc != 0) + throw error_t(); + } + + void disconnect(std::string const &addr) { disconnect(addr.c_str()); } + + void disconnect(const char *addr_) + { + int rc = zmq_disconnect(_handle, addr_); + if (rc != 0) + throw error_t(); + } + + bool connected() const ZMQ_NOTHROW { return (_handle != ZMQ_NULLPTR); } + + ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking a const_buffer and send_flags") + size_t send(const void *buf_, size_t len_, int flags_ = 0) + { + int nbytes = zmq_send(_handle, buf_, len_, flags_); + if (nbytes >= 0) + return static_cast(nbytes); + if (zmq_errno() == EAGAIN) + return 0; + throw error_t(); + } + + ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags") + bool send(message_t &msg_, + int flags_ = 0) // default until removed + { + int nbytes = zmq_msg_send(msg_.handle(), _handle, flags_); + if (nbytes >= 0) + return true; + if (zmq_errno() == EAGAIN) + return false; + throw error_t(); + } + + template + ZMQ_CPP11_DEPRECATED( + "from 4.4.1, use send taking message_t or buffer (for contiguous " + "ranges), and send_flags") + bool send(T first, T last, int flags_ = 0) + { + zmq::message_t msg(first, last); + int nbytes = zmq_msg_send(msg.handle(), _handle, flags_); + if (nbytes >= 0) + return true; + if (zmq_errno() == EAGAIN) + return false; + throw error_t(); + } + +#ifdef ZMQ_HAS_RVALUE_REFS + ZMQ_CPP11_DEPRECATED("from 4.3.1, use send taking message_t and send_flags") + bool send(message_t &&msg_, + int flags_ = 0) // default until removed + { +#ifdef ZMQ_CPP11 + return send(msg_, static_cast(flags_)).has_value(); +#else + return send(msg_, flags_); +#endif + } +#endif + +#ifdef ZMQ_CPP11 + send_result_t send(const_buffer buf, send_flags flags = send_flags::none) + { + const int nbytes = + zmq_send(_handle, buf.data(), buf.size(), static_cast(flags)); + if (nbytes >= 0) + return static_cast(nbytes); + if (zmq_errno() == EAGAIN) + return {}; + throw error_t(); + } + + send_result_t send(message_t &msg, send_flags flags) + { + int nbytes = zmq_msg_send(msg.handle(), _handle, static_cast(flags)); + if (nbytes >= 0) + return static_cast(nbytes); + if (zmq_errno() == EAGAIN) + return {}; + throw error_t(); + } + + send_result_t send(message_t &&msg, send_flags flags) + { + return send(msg, flags); + } +#endif + + ZMQ_CPP11_DEPRECATED( + "from 4.3.1, use recv taking a mutable_buffer and recv_flags") + size_t recv(void *buf_, size_t len_, int flags_ = 0) + { + int nbytes = zmq_recv(_handle, buf_, len_, flags_); + if (nbytes >= 0) + return static_cast(nbytes); + if (zmq_errno() == EAGAIN) + return 0; + throw error_t(); + } + + ZMQ_CPP11_DEPRECATED( + "from 4.3.1, use recv taking a reference to message_t and recv_flags") + bool recv(message_t *msg_, int flags_ = 0) + { + int nbytes = zmq_msg_recv(msg_->handle(), _handle, flags_); + if (nbytes >= 0) + return true; + if (zmq_errno() == EAGAIN) + return false; + throw error_t(); + } + +#ifdef ZMQ_CPP11 + ZMQ_NODISCARD + recv_buffer_result_t recv(mutable_buffer buf, + recv_flags flags = recv_flags::none) + { + const int nbytes = + zmq_recv(_handle, buf.data(), buf.size(), static_cast(flags)); + if (nbytes >= 0) { + return recv_buffer_size{ + (std::min)(static_cast(nbytes), buf.size()), + static_cast(nbytes)}; + } + if (zmq_errno() == EAGAIN) + return {}; + throw error_t(); + } + + ZMQ_NODISCARD + recv_result_t recv(message_t &msg, recv_flags flags = recv_flags::none) + { + const int nbytes = + zmq_msg_recv(msg.handle(), _handle, static_cast(flags)); + if (nbytes >= 0) { + assert(msg.size() == static_cast(nbytes)); + return static_cast(nbytes); + } + if (zmq_errno() == EAGAIN) + return {}; + throw error_t(); + } +#endif + +#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0) + void join(const char *group) + { + int rc = zmq_join(_handle, group); + if (rc != 0) + throw error_t(); + } + + void leave(const char *group) + { + int rc = zmq_leave(_handle, group); + if (rc != 0) + throw error_t(); + } +#endif + + ZMQ_NODISCARD void *handle() ZMQ_NOTHROW { return _handle; } + ZMQ_NODISCARD const void *handle() const ZMQ_NOTHROW { return _handle; } + + ZMQ_EXPLICIT operator bool() const ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; } + // note: non-const operator bool can be removed once + // operator void* is removed from socket_t + ZMQ_EXPLICIT operator bool() ZMQ_NOTHROW { return _handle != ZMQ_NULLPTR; } + + protected: + void *_handle; + + private: + void set_option(int option_, const void *optval_, size_t optvallen_) + { + int rc = zmq_setsockopt(_handle, option_, optval_, optvallen_); + if (rc != 0) + throw error_t(); + } + + void get_option(int option_, void *optval_, size_t *optvallen_) const + { + int rc = zmq_getsockopt(_handle, option_, optval_, optvallen_); + if (rc != 0) + throw error_t(); + } +}; +} // namespace detail + +#ifdef ZMQ_CPP11 +enum class socket_type : int +{ + req = ZMQ_REQ, + rep = ZMQ_REP, + dealer = ZMQ_DEALER, + router = ZMQ_ROUTER, + pub = ZMQ_PUB, + sub = ZMQ_SUB, + xpub = ZMQ_XPUB, + xsub = ZMQ_XSUB, + push = ZMQ_PUSH, + pull = ZMQ_PULL, +#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0) + server = ZMQ_SERVER, + client = ZMQ_CLIENT, + radio = ZMQ_RADIO, + dish = ZMQ_DISH, +#endif +#if ZMQ_VERSION_MAJOR >= 4 + stream = ZMQ_STREAM, +#endif + pair = ZMQ_PAIR +}; +#endif + +struct from_handle_t +{ + struct _private + { + }; // disabling use other than with from_handle + ZMQ_CONSTEXPR_FN ZMQ_EXPLICIT from_handle_t(_private /*p*/) ZMQ_NOTHROW {} +}; + +ZMQ_CONSTEXPR_VAR from_handle_t from_handle = + from_handle_t(from_handle_t::_private()); + +// A non-owning nullable reference to a socket. +// The reference is invalidated on socket close or destruction. +class socket_ref : public detail::socket_base +{ + public: + socket_ref() ZMQ_NOTHROW : detail::socket_base() {} +#ifdef ZMQ_CPP11 + socket_ref(std::nullptr_t) ZMQ_NOTHROW : detail::socket_base() {} +#endif + socket_ref(from_handle_t /*fh*/, void *handle) ZMQ_NOTHROW + : detail::socket_base(handle) + { + } +}; + +#ifdef ZMQ_CPP11 +inline bool operator==(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW +{ + return sr.handle() == nullptr; +} +inline bool operator==(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW +{ + return sr.handle() == nullptr; +} +inline bool operator!=(socket_ref sr, std::nullptr_t /*p*/) ZMQ_NOTHROW +{ + return !(sr == nullptr); +} +inline bool operator!=(std::nullptr_t /*p*/, socket_ref sr) ZMQ_NOTHROW +{ + return !(sr == nullptr); +} +#endif + +inline bool operator==(socket_ref a, socket_ref b) ZMQ_NOTHROW +{ + return std::equal_to()(a.handle(), b.handle()); +} +inline bool operator!=(socket_ref a, socket_ref b) ZMQ_NOTHROW +{ + return !(a == b); +} +inline bool operator<(socket_ref a, socket_ref b) ZMQ_NOTHROW +{ + return std::less()(a.handle(), b.handle()); +} +inline bool operator>(socket_ref a, socket_ref b) ZMQ_NOTHROW +{ + return b < a; +} +inline bool operator<=(socket_ref a, socket_ref b) ZMQ_NOTHROW +{ + return !(a > b); +} +inline bool operator>=(socket_ref a, socket_ref b) ZMQ_NOTHROW +{ + return !(a < b); +} + +} // namespace zmq + +#ifdef ZMQ_CPP11 +namespace std +{ +template<> struct hash +{ + size_t operator()(zmq::socket_ref sr) const ZMQ_NOTHROW + { + return hash()(sr.handle()); + } +}; +} // namespace std +#endif + +namespace zmq +{ +class socket_t : public detail::socket_base +{ + friend class monitor_t; + + public: + socket_t() ZMQ_NOTHROW : detail::socket_base(ZMQ_NULLPTR), ctxptr(ZMQ_NULLPTR) {} + + socket_t(context_t &context_, int type_) : + detail::socket_base(zmq_socket(context_.handle(), type_)), + ctxptr(context_.handle()) + { + if (_handle == ZMQ_NULLPTR) + throw error_t(); + } + +#ifdef ZMQ_CPP11 + socket_t(context_t &context_, socket_type type_) : + socket_t(context_, static_cast(type_)) + { + } +#endif + +#ifdef ZMQ_HAS_RVALUE_REFS + socket_t(socket_t &&rhs) ZMQ_NOTHROW : detail::socket_base(rhs._handle), + ctxptr(rhs.ctxptr) + { + rhs._handle = ZMQ_NULLPTR; + rhs.ctxptr = ZMQ_NULLPTR; + } + socket_t &operator=(socket_t &&rhs) ZMQ_NOTHROW + { + close(); + std::swap(_handle, rhs._handle); + std::swap(ctxptr, rhs.ctxptr); + return *this; + } +#endif + + ~socket_t() ZMQ_NOTHROW { close(); } + + operator void *() ZMQ_NOTHROW { return _handle; } + + operator void const *() const ZMQ_NOTHROW { return _handle; } + + void close() ZMQ_NOTHROW + { + if (_handle == ZMQ_NULLPTR) + // already closed + return; + int rc = zmq_close(_handle); + ZMQ_ASSERT(rc == 0); + _handle = ZMQ_NULLPTR; + ctxptr = ZMQ_NULLPTR; + } + + void swap(socket_t &other) ZMQ_NOTHROW + { + std::swap(_handle, other._handle); + std::swap(ctxptr, other.ctxptr); + } + + operator socket_ref() ZMQ_NOTHROW { return socket_ref(from_handle, _handle); } + + private: + void *ctxptr; + + socket_t(const socket_t &) ZMQ_DELETED_FUNCTION; + void operator=(const socket_t &) ZMQ_DELETED_FUNCTION; + + // used by monitor_t + socket_t(void *context_, int type_) : + detail::socket_base(zmq_socket(context_, type_)), + ctxptr(context_) + { + if (_handle == ZMQ_NULLPTR) + throw error_t(); + if (ctxptr == ZMQ_NULLPTR) + throw error_t(); + } +}; + +inline void swap(socket_t &a, socket_t &b) ZMQ_NOTHROW +{ + a.swap(b); +} + +ZMQ_DEPRECATED("from 4.3.1, use proxy taking socket_t objects") +inline void proxy(void *frontend, void *backend, void *capture) +{ + int rc = zmq_proxy(frontend, backend, capture); + if (rc != 0) + throw error_t(); +} + +inline void +proxy(socket_ref frontend, socket_ref backend, socket_ref capture = socket_ref()) +{ + int rc = zmq_proxy(frontend.handle(), backend.handle(), capture.handle()); + if (rc != 0) + throw error_t(); +} + +#ifdef ZMQ_HAS_PROXY_STEERABLE +ZMQ_DEPRECATED("from 4.3.1, use proxy_steerable taking socket_t objects") +inline void +proxy_steerable(void *frontend, void *backend, void *capture, void *control) +{ + int rc = zmq_proxy_steerable(frontend, backend, capture, control); + if (rc != 0) + throw error_t(); +} + +inline void proxy_steerable(socket_ref frontend, + socket_ref backend, + socket_ref capture, + socket_ref control) +{ + int rc = zmq_proxy_steerable(frontend.handle(), backend.handle(), + capture.handle(), control.handle()); + if (rc != 0) + throw error_t(); +} +#endif + +class monitor_t +{ + public: + monitor_t() : _socket(), _monitor_socket() {} + + virtual ~monitor_t() { close(); } + +#ifdef ZMQ_HAS_RVALUE_REFS + monitor_t(monitor_t &&rhs) ZMQ_NOTHROW : _socket(), _monitor_socket() + { + std::swap(_socket, rhs._socket); + std::swap(_monitor_socket, rhs._monitor_socket); + } + + monitor_t &operator=(monitor_t &&rhs) ZMQ_NOTHROW + { + close(); + _socket = socket_ref(); + std::swap(_socket, rhs._socket); + std::swap(_monitor_socket, rhs._monitor_socket); + return *this; + } +#endif + + + void + monitor(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL) + { + monitor(socket, addr.c_str(), events); + } + + void monitor(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL) + { + init(socket, addr_, events); + while (true) { + check_event(-1); + } + } + + void init(socket_t &socket, std::string const &addr, int events = ZMQ_EVENT_ALL) + { + init(socket, addr.c_str(), events); + } + + void init(socket_t &socket, const char *addr_, int events = ZMQ_EVENT_ALL) + { + int rc = zmq_socket_monitor(socket.handle(), addr_, events); + if (rc != 0) + throw error_t(); + + _socket = socket; + _monitor_socket = socket_t(socket.ctxptr, ZMQ_PAIR); + _monitor_socket.connect(addr_); + + on_monitor_started(); + } + + bool check_event(int timeout = 0) + { + assert(_monitor_socket); + + zmq_msg_t eventMsg; + zmq_msg_init(&eventMsg); + + zmq::pollitem_t items[] = { + {_monitor_socket.handle(), 0, ZMQ_POLLIN, 0}, + }; + + zmq::poll(&items[0], 1, timeout); + + if (items[0].revents & ZMQ_POLLIN) { + int rc = zmq_msg_recv(&eventMsg, _monitor_socket.handle(), 0); + if (rc == -1 && zmq_errno() == ETERM) + return false; + assert(rc != -1); + + } else { + zmq_msg_close(&eventMsg); + return false; + } + +#if ZMQ_VERSION_MAJOR >= 4 + const char *data = static_cast(zmq_msg_data(&eventMsg)); + zmq_event_t msgEvent; + memcpy(&msgEvent.event, data, sizeof(uint16_t)); + data += sizeof(uint16_t); + memcpy(&msgEvent.value, data, sizeof(int32_t)); + zmq_event_t *event = &msgEvent; +#else + zmq_event_t *event = static_cast(zmq_msg_data(&eventMsg)); +#endif + +#ifdef ZMQ_NEW_MONITOR_EVENT_LAYOUT + zmq_msg_t addrMsg; + zmq_msg_init(&addrMsg); + int rc = zmq_msg_recv(&addrMsg, _monitor_socket.handle(), 0); + if (rc == -1 && zmq_errno() == ETERM) { + zmq_msg_close(&eventMsg); + return false; + } + + assert(rc != -1); + const char *str = static_cast(zmq_msg_data(&addrMsg)); + std::string address(str, str + zmq_msg_size(&addrMsg)); + zmq_msg_close(&addrMsg); +#else + // Bit of a hack, but all events in the zmq_event_t union have the same layout so this will work for all event types. + std::string address = event->data.connected.addr; +#endif + +#ifdef ZMQ_EVENT_MONITOR_STOPPED + if (event->event == ZMQ_EVENT_MONITOR_STOPPED) { + zmq_msg_close(&eventMsg); + return false; + } + +#endif + + switch (event->event) { + case ZMQ_EVENT_CONNECTED: + on_event_connected(*event, address.c_str()); + break; + case ZMQ_EVENT_CONNECT_DELAYED: + on_event_connect_delayed(*event, address.c_str()); + break; + case ZMQ_EVENT_CONNECT_RETRIED: + on_event_connect_retried(*event, address.c_str()); + break; + case ZMQ_EVENT_LISTENING: + on_event_listening(*event, address.c_str()); + break; + case ZMQ_EVENT_BIND_FAILED: + on_event_bind_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_ACCEPTED: + on_event_accepted(*event, address.c_str()); + break; + case ZMQ_EVENT_ACCEPT_FAILED: + on_event_accept_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_CLOSED: + on_event_closed(*event, address.c_str()); + break; + case ZMQ_EVENT_CLOSE_FAILED: + on_event_close_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_DISCONNECTED: + on_event_disconnected(*event, address.c_str()); + break; +#ifdef ZMQ_BUILD_DRAFT_API +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3) + case ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL: + on_event_handshake_failed_no_detail(*event, address.c_str()); + break; + case ZMQ_EVENT_HANDSHAKE_FAILED_PROTOCOL: + on_event_handshake_failed_protocol(*event, address.c_str()); + break; + case ZMQ_EVENT_HANDSHAKE_FAILED_AUTH: + on_event_handshake_failed_auth(*event, address.c_str()); + break; + case ZMQ_EVENT_HANDSHAKE_SUCCEEDED: + on_event_handshake_succeeded(*event, address.c_str()); + break; +#elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1) + case ZMQ_EVENT_HANDSHAKE_FAILED: + on_event_handshake_failed(*event, address.c_str()); + break; + case ZMQ_EVENT_HANDSHAKE_SUCCEED: + on_event_handshake_succeed(*event, address.c_str()); + break; +#endif +#endif + default: + on_event_unknown(*event, address.c_str()); + break; + } + zmq_msg_close(&eventMsg); + + return true; + } + +#ifdef ZMQ_EVENT_MONITOR_STOPPED + void abort() + { + if (_socket) + zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0); + + _socket = socket_ref(); + } +#endif + virtual void on_monitor_started() {} + virtual void on_event_connected(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_connect_delayed(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_connect_retried(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_listening(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_bind_failed(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_accepted(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_accept_failed(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_closed(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_close_failed(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_disconnected(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3) + virtual void on_event_handshake_failed_no_detail(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_handshake_failed_protocol(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_handshake_failed_auth(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_handshake_succeeded(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } +#elif ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 1) + virtual void on_event_handshake_failed(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } + virtual void on_event_handshake_succeed(const zmq_event_t &event_, + const char *addr_) + { + (void) event_; + (void) addr_; + } +#endif + virtual void on_event_unknown(const zmq_event_t &event_, const char *addr_) + { + (void) event_; + (void) addr_; + } + + private: + monitor_t(const monitor_t &) ZMQ_DELETED_FUNCTION; + void operator=(const monitor_t &) ZMQ_DELETED_FUNCTION; + + socket_ref _socket; + socket_t _monitor_socket; + + void close() ZMQ_NOTHROW + { + if (_socket) + zmq_socket_monitor(_socket.handle(), ZMQ_NULLPTR, 0); + _monitor_socket.close(); + } +}; + +#if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER) + +// polling events +enum class event_flags : short +{ + none = 0, + pollin = ZMQ_POLLIN, + pollout = ZMQ_POLLOUT, + pollerr = ZMQ_POLLERR, + pollpri = ZMQ_POLLPRI +}; + +constexpr event_flags operator|(event_flags a, event_flags b) noexcept +{ + return detail::enum_bit_or(a, b); +} +constexpr event_flags operator&(event_flags a, event_flags b) noexcept +{ + return detail::enum_bit_and(a, b); +} +constexpr event_flags operator^(event_flags a, event_flags b) noexcept +{ + return detail::enum_bit_xor(a, b); +} +constexpr event_flags operator~(event_flags a) noexcept +{ + return detail::enum_bit_not(a); +} + +struct no_user_data; + +// layout compatible with zmq_poller_event_t +template struct poller_event +{ + socket_ref socket; +#ifdef _WIN32 + SOCKET fd; +#else + int fd; +#endif + T *user_data; + event_flags events; +}; + +template class poller_t +{ + public: + using event_type = poller_event; + + poller_t() : poller_ptr(zmq_poller_new()) + { + if (!poller_ptr) + throw error_t(); + } + + template< + typename Dummy = void, + typename = + typename std::enable_if::value, Dummy>::type> + void add(zmq::socket_ref socket, event_flags events, T *user_data) + { + add_impl(socket, events, user_data); + } + + void add(zmq::socket_ref socket, event_flags events) + { + add_impl(socket, events, nullptr); + } + + void remove(zmq::socket_ref socket) + { + if (0 != zmq_poller_remove(poller_ptr.get(), socket.handle())) { + throw error_t(); + } + } + + void modify(zmq::socket_ref socket, event_flags events) + { + if (0 + != zmq_poller_modify(poller_ptr.get(), socket.handle(), + static_cast(events))) { + throw error_t(); + } + } + + size_t wait_all(std::vector &poller_events, + const std::chrono::milliseconds timeout) + { + int rc = zmq_poller_wait_all( + poller_ptr.get(), + reinterpret_cast(poller_events.data()), + static_cast(poller_events.size()), + static_cast(timeout.count())); + if (rc > 0) + return static_cast(rc); + +#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 3) + if (zmq_errno() == EAGAIN) +#else + if (zmq_errno() == ETIMEDOUT) +#endif + return 0; + + throw error_t(); + } + + private: + struct destroy_poller_t + { + void operator()(void *ptr) noexcept + { + int rc = zmq_poller_destroy(&ptr); + ZMQ_ASSERT(rc == 0); + } + }; + + std::unique_ptr poller_ptr; + + void add_impl(zmq::socket_ref socket, event_flags events, T *user_data) + { + if (0 + != zmq_poller_add(poller_ptr.get(), socket.handle(), user_data, + static_cast(events))) { + throw error_t(); + } + } +}; +#endif // defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER) + +inline std::ostream &operator<<(std::ostream &os, const message_t &msg) +{ + return os << msg.str(); +} + +} // namespace zmq + +#endif // __ZMQ_HPP_INCLUDED__ diff --git a/include/zmq_addon.hpp b/include/zmq_addon.hpp new file mode 100644 index 000000000..021ab9540 --- /dev/null +++ b/include/zmq_addon.hpp @@ -0,0 +1,743 @@ +/* + Copyright (c) 2016-2017 ZeroMQ community + Copyright (c) 2016 VOCA AS / Harald Nøkland + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +*/ + +#ifndef __ZMQ_ADDON_HPP_INCLUDED__ +#define __ZMQ_ADDON_HPP_INCLUDED__ + +#include "zmq.hpp" + +#include +#include +#include +#include +#ifdef ZMQ_CPP11 +#include +#include +#include +#endif + +namespace zmq +{ +#ifdef ZMQ_CPP11 + +namespace detail +{ +template +recv_result_t +recv_multipart_n(socket_ref s, OutputIt out, size_t n, recv_flags flags) +{ + size_t msg_count = 0; + message_t msg; + while (true) { + if (CheckN) { + if (msg_count >= n) + throw std::runtime_error( + "Too many message parts in recv_multipart_n"); + } + if (!s.recv(msg, flags)) { + // zmq ensures atomic delivery of messages + assert(msg_count == 0); + return {}; + } + ++msg_count; + const bool more = msg.more(); + *out++ = std::move(msg); + if (!more) + break; + } + return msg_count; +} + +inline bool is_little_endian() +{ + const uint16_t i = 0x01; + return *reinterpret_cast(&i) == 0x01; +} + +inline void write_network_order(unsigned char *buf, const uint32_t value) +{ + if (is_little_endian()) { + ZMQ_CONSTEXPR_VAR uint32_t mask = std::numeric_limits::max(); + *buf++ = (value >> 24) & mask; + *buf++ = (value >> 16) & mask; + *buf++ = (value >> 8) & mask; + *buf++ = value & mask; + } else { + std::memcpy(buf, &value, sizeof(value)); + } +} + +inline uint32_t read_u32_network_order(const unsigned char *buf) +{ + if (is_little_endian()) { + return (static_cast(buf[0]) << 24) + + (static_cast(buf[1]) << 16) + + (static_cast(buf[2]) << 8) + + static_cast(buf[3]); + } else { + uint32_t value; + std::memcpy(&value, buf, sizeof(value)); + return value; + } +} +} // namespace detail + +/* Receive a multipart message. + + Writes the zmq::message_t objects to OutputIterator out. + The out iterator must handle an unspecified number of writes, + e.g. by using std::back_inserter. + + Returns: the number of messages received or nullopt (on EAGAIN). + Throws: if recv throws. Any exceptions thrown + by the out iterator will be propagated and the message + may have been only partially received with pending + message parts. It is adviced to close this socket in that event. +*/ +template +ZMQ_NODISCARD recv_result_t recv_multipart(socket_ref s, + OutputIt out, + recv_flags flags = recv_flags::none) +{ + return detail::recv_multipart_n(s, std::move(out), 0, flags); +} + +/* Receive a multipart message. + + Writes at most n zmq::message_t objects to OutputIterator out. + If the number of message parts of the incoming message exceeds n + then an exception will be thrown. + + Returns: the number of messages received or nullopt (on EAGAIN). + Throws: if recv throws. Throws std::runtime_error if the number + of message parts exceeds n (exactly n messages will have been written + to out). Any exceptions thrown + by the out iterator will be propagated and the message + may have been only partially received with pending + message parts. It is adviced to close this socket in that event. +*/ +template +ZMQ_NODISCARD recv_result_t recv_multipart_n(socket_ref s, + OutputIt out, + size_t n, + recv_flags flags = recv_flags::none) +{ + return detail::recv_multipart_n(s, std::move(out), n, flags); +} + +/* Send a multipart message. + + The range must be a ForwardRange of zmq::message_t, + zmq::const_buffer or zmq::mutable_buffer. + The flags may be zmq::send_flags::sndmore if there are + more message parts to be sent after the call to this function. + + Returns: the number of messages sent (exactly msgs.size()) or nullopt (on EAGAIN). + Throws: if send throws. Any exceptions thrown + by the msgs range will be propagated and the message + may have been only partially sent. It is adviced to close this socket in that event. +*/ +template::value + && (std::is_same, message_t>::value + || detail::is_buffer>::value)>::type +#endif + > +send_result_t +send_multipart(socket_ref s, Range &&msgs, send_flags flags = send_flags::none) +{ + using std::begin; + using std::end; + auto it = begin(msgs); + const auto end_it = end(msgs); + size_t msg_count = 0; + while (it != end_it) { + const auto next = std::next(it); + const auto msg_flags = + flags | (next == end_it ? send_flags::none : send_flags::sndmore); + if (!s.send(*it, msg_flags)) { + // zmq ensures atomic delivery of messages + assert(it == begin(msgs)); + return {}; + } + ++msg_count; + it = next; + } + return msg_count; +} + +/* Encode a multipart message. + + The range must be a ForwardRange of zmq::message_t. A + zmq::multipart_t or STL container may be passed for encoding. + + Returns: a zmq::message_t holding the encoded multipart data. + + Throws: std::range_error is thrown if the size of any single part + can not fit in an unsigned 32 bit integer. + + The encoding is compatible with that used by the CZMQ function + zmsg_encode(), see https://rfc.zeromq.org/spec/50/. + Each part consists of a size followed by the data. + These are placed contiguously into the output message. A part of + size less than 255 bytes will have a single byte size value. + Larger parts will have a five byte size value with the first byte + set to 0xFF and the remaining four bytes holding the size of the + part's data. +*/ +template::value + && (std::is_same, message_t>::value + || detail::is_buffer>::value)>::type +#endif + > +message_t encode(const Range &parts) +{ + size_t mmsg_size = 0; + + // First pass check sizes + for (const auto &part : parts) { + const size_t part_size = part.size(); + if (part_size > std::numeric_limits::max()) { + // Size value must fit into uint32_t. + throw std::range_error("Invalid size, message part too large"); + } + const size_t count_size = + part_size < std::numeric_limits::max() ? 1 : 5; + mmsg_size += part_size + count_size; + } + + message_t encoded(mmsg_size); + unsigned char *buf = encoded.data(); + for (const auto &part : parts) { + const uint32_t part_size = part.size(); + const unsigned char *part_data = + static_cast(part.data()); + + if (part_size < std::numeric_limits::max()) { + // small part + *buf++ = (unsigned char) part_size; + } else { + // big part + *buf++ = std::numeric_limits::max(); + detail::write_network_order(buf, part_size); + buf += sizeof(part_size); + } + std::memcpy(buf, part_data, part_size); + buf += part_size; + } + + assert(static_cast(buf - encoded.data()) == mmsg_size); + return encoded; +} + +/* Decode an encoded message to multiple parts. + + The given output iterator must be a ForwardIterator to a container + holding zmq::message_t such as a zmq::multipart_t or various STL + containers. + + Returns the ForwardIterator advanced once past the last decoded + part. + + Throws: a std::out_of_range is thrown if the encoded part sizes + lead to exceeding the message data bounds. + + The decoding assumes the message is encoded in the manner + performed by zmq::encode(), see https://rfc.zeromq.org/spec/50/. + */ +template OutputIt decode(const message_t &encoded, OutputIt out) +{ + const unsigned char *source = encoded.data(); + const unsigned char *const limit = source + encoded.size(); + + while (source < limit) { + size_t part_size = *source++; + if (part_size == std::numeric_limits::max()) { + if (static_cast(limit - source) < sizeof(uint32_t)) { + throw std::out_of_range( + "Malformed encoding, overflow in reading size"); + } + part_size = detail::read_u32_network_order(source); + // the part size is allowed to be less than 0xFF + source += sizeof(uint32_t); + } + + if (static_cast(limit - source) < part_size) { + throw std::out_of_range("Malformed encoding, overflow in reading part"); + } + *out = message_t(source, part_size); + ++out; + source += part_size; + } + + assert(source == limit); + return out; +} + +#endif + + +#ifdef ZMQ_HAS_RVALUE_REFS + +/* + This class handles multipart messaging. It is the C++ equivalent of zmsg.h, + which is part of CZMQ (the high-level C binding). Furthermore, it is a major + improvement compared to zmsg.hpp, which is part of the examples in the ØMQ + Guide. Unnecessary copying is avoided by using move semantics to efficiently + add/remove parts. +*/ +class multipart_t +{ + private: + std::deque m_parts; + + public: + typedef std::deque::value_type value_type; + + typedef std::deque::iterator iterator; + typedef std::deque::const_iterator const_iterator; + + typedef std::deque::reverse_iterator reverse_iterator; + typedef std::deque::const_reverse_iterator const_reverse_iterator; + + // Default constructor + multipart_t() {} + + // Construct from socket receive + multipart_t(socket_t &socket) { recv(socket); } + + // Construct from memory block + multipart_t(const void *src, size_t size) { addmem(src, size); } + + // Construct from string + multipart_t(const std::string &string) { addstr(string); } + + // Construct from message part + multipart_t(message_t &&message) { add(std::move(message)); } + + // Move constructor + multipart_t(multipart_t &&other) { m_parts = std::move(other.m_parts); } + + // Move assignment operator + multipart_t &operator=(multipart_t &&other) + { + m_parts = std::move(other.m_parts); + return *this; + } + + // Destructor + virtual ~multipart_t() { clear(); } + + message_t &operator[](size_t n) { return m_parts[n]; } + + const message_t &operator[](size_t n) const { return m_parts[n]; } + + message_t &at(size_t n) { return m_parts.at(n); } + + const message_t &at(size_t n) const { return m_parts.at(n); } + + iterator begin() { return m_parts.begin(); } + + const_iterator begin() const { return m_parts.begin(); } + + const_iterator cbegin() const { return m_parts.cbegin(); } + + reverse_iterator rbegin() { return m_parts.rbegin(); } + + const_reverse_iterator rbegin() const { return m_parts.rbegin(); } + + iterator end() { return m_parts.end(); } + + const_iterator end() const { return m_parts.end(); } + + const_iterator cend() const { return m_parts.cend(); } + + reverse_iterator rend() { return m_parts.rend(); } + + const_reverse_iterator rend() const { return m_parts.rend(); } + + // Delete all parts + void clear() { m_parts.clear(); } + + // Get number of parts + size_t size() const { return m_parts.size(); } + + // Check if number of parts is zero + bool empty() const { return m_parts.empty(); } + + // Receive multipart message from socket + bool recv(socket_t &socket, int flags = 0) + { + clear(); + bool more = true; + while (more) { + message_t message; +#ifdef ZMQ_CPP11 + if (!socket.recv(message, static_cast(flags))) + return false; +#else + if (!socket.recv(&message, flags)) + return false; +#endif + more = message.more(); + add(std::move(message)); + } + return true; + } + + // Send multipart message to socket + bool send(socket_t &socket, int flags = 0) + { + flags &= ~(ZMQ_SNDMORE); + bool more = size() > 0; + while (more) { + message_t message = pop(); + more = size() > 0; +#ifdef ZMQ_CPP11 + if (!socket.send(message, static_cast( + (more ? ZMQ_SNDMORE : 0) | flags))) + return false; +#else + if (!socket.send(message, (more ? ZMQ_SNDMORE : 0) | flags)) + return false; +#endif + } + clear(); + return true; + } + + // Concatenate other multipart to front + void prepend(multipart_t &&other) + { + while (!other.empty()) + push(other.remove()); + } + + // Concatenate other multipart to back + void append(multipart_t &&other) + { + while (!other.empty()) + add(other.pop()); + } + + // Push memory block to front + void pushmem(const void *src, size_t size) + { + m_parts.push_front(message_t(src, size)); + } + + // Push memory block to back + void addmem(const void *src, size_t size) + { + m_parts.push_back(message_t(src, size)); + } + + // Push string to front + void pushstr(const std::string &string) + { + m_parts.push_front(message_t(string.data(), string.size())); + } + + // Push string to back + void addstr(const std::string &string) + { + m_parts.push_back(message_t(string.data(), string.size())); + } + + // Push type (fixed-size) to front + template void pushtyp(const T &type) + { + static_assert(!std::is_same::value, + "Use pushstr() instead of pushtyp()"); + m_parts.push_front(message_t(&type, sizeof(type))); + } + + // Push type (fixed-size) to back + template void addtyp(const T &type) + { + static_assert(!std::is_same::value, + "Use addstr() instead of addtyp()"); + m_parts.push_back(message_t(&type, sizeof(type))); + } + + // Push message part to front + void push(message_t &&message) { m_parts.push_front(std::move(message)); } + + // Push message part to back + void add(message_t &&message) { m_parts.push_back(std::move(message)); } + + // Alias to allow std::back_inserter() + void push_back(message_t &&message) { m_parts.push_back(std::move(message)); } + + // Pop string from front + std::string popstr() + { + std::string string(m_parts.front().data(), m_parts.front().size()); + m_parts.pop_front(); + return string; + } + + // Pop type (fixed-size) from front + template T poptyp() + { + static_assert(!std::is_same::value, + "Use popstr() instead of poptyp()"); + if (sizeof(T) != m_parts.front().size()) + throw std::runtime_error( + "Invalid type, size does not match the message size"); + T type = *m_parts.front().data(); + m_parts.pop_front(); + return type; + } + + // Pop message part from front + message_t pop() + { + message_t message = std::move(m_parts.front()); + m_parts.pop_front(); + return message; + } + + // Pop message part from back + message_t remove() + { + message_t message = std::move(m_parts.back()); + m_parts.pop_back(); + return message; + } + + // get message part from front + const message_t &front() { return m_parts.front(); } + + // get message part from back + const message_t &back() { return m_parts.back(); } + + // Get pointer to a specific message part + const message_t *peek(size_t index) const { return &m_parts[index]; } + + // Get a string copy of a specific message part + std::string peekstr(size_t index) const + { + std::string string(m_parts[index].data(), m_parts[index].size()); + return string; + } + + // Peek type (fixed-size) from front + template T peektyp(size_t index) const + { + static_assert(!std::is_same::value, + "Use peekstr() instead of peektyp()"); + if (sizeof(T) != m_parts[index].size()) + throw std::runtime_error( + "Invalid type, size does not match the message size"); + T type = *m_parts[index].data(); + return type; + } + + // Create multipart from type (fixed-size) + template static multipart_t create(const T &type) + { + multipart_t multipart; + multipart.addtyp(type); + return multipart; + } + + // Copy multipart + multipart_t clone() const + { + multipart_t multipart; + for (size_t i = 0; i < size(); i++) + multipart.addmem(m_parts[i].data(), m_parts[i].size()); + return multipart; + } + + // Dump content to string + std::string str() const + { + std::stringstream ss; + for (size_t i = 0; i < m_parts.size(); i++) { + const unsigned char *data = m_parts[i].data(); + size_t size = m_parts[i].size(); + + // Dump the message as text or binary + bool isText = true; + for (size_t j = 0; j < size; j++) { + if (data[j] < 32 || data[j] > 127) { + isText = false; + break; + } + } + ss << "\n[" << std::dec << std::setw(3) << std::setfill('0') << size + << "] "; + if (size >= 1000) { + ss << "... (too big to print)"; + continue; + } + for (size_t j = 0; j < size; j++) { + if (isText) + ss << static_cast(data[j]); + else + ss << std::hex << std::setw(2) << std::setfill('0') + << static_cast(data[j]); + } + } + return ss.str(); + } + + // Check if equal to other multipart + bool equal(const multipart_t *other) const + { + if (size() != other->size()) + return false; + for (size_t i = 0; i < size(); i++) + if (*peek(i) != *other->peek(i)) + return false; + return true; + } + +#ifdef ZMQ_CPP11 + + // Return single part message_t encoded from this multipart_t. + message_t encode() const { return zmq::encode(*this); } + + // Decode encoded message into multiple parts and append to self. + void decode_append(const message_t &encoded) + { + zmq::decode(encoded, std::back_inserter(*this)); + } + + // Return a new multipart_t containing the decoded message_t. + static multipart_t decode(const message_t &encoded) + { + multipart_t tmp; + zmq::decode(encoded, std::back_inserter(tmp)); + return tmp; + } + +#endif + + private: + // Disable implicit copying (moving is more efficient) + multipart_t(const multipart_t &other) ZMQ_DELETED_FUNCTION; + void operator=(const multipart_t &other) ZMQ_DELETED_FUNCTION; +}; // class multipart_t + +inline std::ostream &operator<<(std::ostream &os, const multipart_t &msg) +{ + return os << msg.str(); +} + +#endif // ZMQ_HAS_RVALUE_REFS + +#if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER) +class active_poller_t +{ + public: + active_poller_t() = default; + ~active_poller_t() = default; + + active_poller_t(const active_poller_t &) = delete; + active_poller_t &operator=(const active_poller_t &) = delete; + + active_poller_t(active_poller_t &&src) = default; + active_poller_t &operator=(active_poller_t &&src) = default; + + using handler_type = std::function; + + void add(zmq::socket_ref socket, event_flags events, handler_type handler) + { + if (!handler) + throw std::invalid_argument("null handler in active_poller_t::add"); + auto ret = handlers.emplace( + socket, std::make_shared(std::move(handler))); + if (!ret.second) + throw error_t(EINVAL); // already added + try { + base_poller.add(socket, events, ret.first->second.get()); + need_rebuild = true; + } + catch (...) { + // rollback + handlers.erase(socket); + throw; + } + } + + void remove(zmq::socket_ref socket) + { + base_poller.remove(socket); + handlers.erase(socket); + need_rebuild = true; + } + + void modify(zmq::socket_ref socket, event_flags events) + { + base_poller.modify(socket, events); + } + + size_t wait(std::chrono::milliseconds timeout) + { + if (need_rebuild) { + poller_events.resize(handlers.size()); + poller_handlers.clear(); + poller_handlers.reserve(handlers.size()); + for (const auto &handler : handlers) { + poller_handlers.push_back(handler.second); + } + need_rebuild = false; + } + const auto count = base_poller.wait_all(poller_events, timeout); + std::for_each(poller_events.begin(), + poller_events.begin() + static_cast(count), + [](decltype(base_poller)::event_type &event) { + assert(event.user_data != nullptr); + (*event.user_data)(event.events); + }); + return count; + } + + ZMQ_NODISCARD bool empty() const noexcept { return handlers.empty(); } + + size_t size() const noexcept { return handlers.size(); } + + private: + bool need_rebuild{false}; + + poller_t base_poller{}; + std::unordered_map> handlers{}; + std::vector poller_events{}; + std::vector> poller_handlers{}; +}; // class active_poller_t +#endif // defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER) + + +} // namespace zmq + +#endif // __ZMQ_ADDON_HPP_INCLUDED__ diff --git a/scripts/ansible_pktg.md b/scripts/ansible_pktg.md index 9f9cfca5a..7c3355f23 100644 --- a/scripts/ansible_pktg.md +++ b/scripts/ansible_pktg.md @@ -1,6 +1,6 @@ # 说明 1. 在主控的中心服务器上需要安装有 ansible 程序。如果没有,可以使用类似 yum install ansible 的命令安装。
2. 将需要安装 packet-agent 的机器加入 ansible 的 hosts 文件:比如添加组 [servers_to_install_pktg] 到 /etc/ansible/hosts,并在该组下加入若干机器IP。
-3. 拷贝待安装的 packet-agent rpm/deb 到 ansible_pktg.yaml 同一目录下。如果待安装的 rpm/deb 不是 yaml 中指定的 netis-packet-agent-0.3.4.el6.x86_64.rpm / netis-packet-agent-0.3.3_amd64.deb,则将 ansible_pktg.yaml 中 rpm_file/deb_file 修改为你需要的文件名。
+3. 拷贝待安装的 packet-agent rpm/deb 到 ansible_pktg.yaml 同一目录下。如果待安装的 rpm/deb 不是 yaml 中指定的 netis-packet-agent-0.5.0.el6.x86_64.rpm / netis-packet-agent-0.5.0_amd64.deb,则将 ansible_pktg.yaml 中 rpm_file/deb_file 修改为你需要的文件名。
4. 执行 ansible-playbook ansible_pktg.yaml 命令,将 packet-agent 程序安装到各个目标机器上。
diff --git a/scripts/ansible_pktg.yaml b/scripts/ansible_pktg.yaml index 46ea587b4..0391d1df1 100644 --- a/scripts/ansible_pktg.yaml +++ b/scripts/ansible_pktg.yaml @@ -2,8 +2,8 @@ - name: install packet-agent and its depends hosts: servers_to_install_pktg vars: - rpm_file: netis-packet-agent-0.3.4.el6.x86_64.rpm - deb_file: netis-packet-agent-0.3.3_amd64.deb + rpm_file: netis-packet-agent-0.5.0.el6.x86_64.rpm + deb_file: netis-packet-agent-0.5.0_amd64.deb remote_user: root gather_facts: True diff --git a/scripts/limit_cpu_mem.md b/scripts/limit_cpu_mem.md index 7a98a447c..19730bf6f 100644 --- a/scripts/limit_cpu_mem.md +++ b/scripts/limit_cpu_mem.md @@ -1,6 +1,6 @@ # 关于 在使用本项目实现网络数据镜像的过程中,常常需要将 pktminerg 安装到需要抓取流量的客户机中。
-为了减少对客户机上其他程序的干扰,就需要对 pktminerg 程序做一些资源使用限制(使用固定的 cpu 核,控制内存用量),可以参考以下两种方法:
+为了减少对客户机上其他程序的干扰,就需要对 pktminerg 程序做一些资源使用限制(使用固定的 cpu 核,控制CPU百分比和内存用量),可以参考以下两种方法:
# 方法1 @@ -11,8 +11,17 @@ # 方法2 使用 scripts 目录下的脚本 limit_cpu_mem.sh 对 pktminerg 的 cpu 和内存做限制。
该脚本使用了 Linux 的 cgroup 机制,对 pktminerg 进程运行的 cpu 和内存进行了控制。
-示例:```sh limit_cpu_mem.sh 2```
-这种方法在 pktminerg 进程重启时,需要重新运行脚本设置。

+示例: +``` +# sh limit_cpu_mem.sh $CPU_SET_ID $CFS_QUOTA_US $MEM_LIMIT +# CPU_SET_ID : 逗号分隔的cpu cores,指定pktminerg运行的核。 +# CFS_QUOTA_US : 每100ms的cpu时间中,分配给pktminerg的时长,单位微秒。 +# MEM_LIMIT: 限制内存用量,可采用M/K/G等单位。无单位则为字节。 +sh limit_cpu_mem.sh 2 10000 800M # 运行在CPU core 2上,10%CPU用量,800M内存限制 +``` +* MEM_LIMIT 对 pcap 缓存无效。pcap 缓存自定义需使用-b参数指定。 +* MEM_LIMIT 仅对第一次配置后新增部分的内存开销有效。 +* 这种方法在 pktminerg 进程重启时,需要重新运行脚本设置。 虽然这种方法同时对 cpu 和内存进行了限制,比上面第一种方法多了对内存的控制,但 pktminerg 程序本身一般占用内存比较固定(大约500M),所以没有特殊需求的情况下,一般推荐第一种方法。
diff --git a/scripts/limit_cpu_mem.sh b/scripts/limit_cpu_mem.sh index 234eb4d49..c33feebef 100644 --- a/scripts/limit_cpu_mem.sh +++ b/scripts/limit_cpu_mem.sh @@ -5,8 +5,8 @@ if [ -e /etc/centos-release ]; then MAJOR_VERSION=`rpm -q --queryformat '%{VERSION}' centos-release` fi -cgroup_pktg_cpu() { - CPU_ID=$1 +cgroup_pktg_cpuset() { + CPU_SET_ID=$1 if [ $MAJOR_VERSION = "6" ]; then cd /cgroup/cpuset @@ -15,14 +15,31 @@ cgroup_pktg_cpu() { fi mkdir -p pktg cd pktg - - echo $CPU_ID > cpuset.cpus + echo $CPU_SET_ID > cpuset.cpus echo 0 > cpuset.mems for pid in `ps -ef | grep pktminerg | grep -v grep | awk '{print $2}'` ; do echo $pid > cgroup.procs; done } +cgroup_pktg_cpu() { + CFS_QUOTA_US=$1 + + if [ $MAJOR_VERSION = "6" ]; then + cd /cgroup/cpu + else + cd /sys/fs/cgroup/cpu + fi + mkdir -p pktg + cd pktg + + echo $CFS_QUOTA_US > cpu.cfs_quota_us + + for pid in `ps -ef | grep pktminerg | grep -v grep | awk '{print $2}'` ; do echo $pid > cgroup.procs; done +} + cgroup_pktg_mem() { + MEM_LIMIT=$1 + if [ $MAJOR_VERSION = "6" ]; then cd /cgroup/memory else @@ -31,25 +48,28 @@ cgroup_pktg_mem() { mkdir -p pktg cd pktg - echo 800M > memory.limit_in_bytes + echo $MEM_LIMIT > memory.limit_in_bytes for pid in `ps -ef | grep pktminerg | grep -v grep | awk '{print $2}'` ; do echo $pid > cgroup.procs; done } cgroup_pktg() { - cgroup_pktg_cpu $1 - cgroup_pktg_mem + cgroup_pktg_cpuset $1 + cgroup_pktg_cpu $2 + cgroup_pktg_mem $3 } -if [ "$1" == "" ] +if [ "$3" == "" ] then echo "Usage:" - echo " sh limit_cpu_mem.sh CPU_ID" - echo " CPU_ID: limit pktminerg to run on this cpu processor id." + echo " sh limit_cpu_mem.sh CPU_SET_ID CFS_QUOTA_US MEM_LIMIT" + echo " CPU_SET_ID: limit pktminerg to run on this cpu processor id." + echo " CFS_QUOTA_US: limit the run-time quota of pktminerg within a period(100ms), in microsecond." + echo " MEM_LIMIT: limit pktminerg memory usage in bytes, such as 800M, 64K, 1024000" echo "Example:" - echo " sh limit_cpu_mem.sh 2" + echo " sh limit_cpu_mem.sh 2 30000 800M # run on cpu2, 30% cpu usage limit, 800MByte memory limit" else - cgroup_pktg $1 + cgroup_pktg $1 $2 $3 fi diff --git a/scripts/postinst b/scripts/postinst new file mode 100644 index 000000000..a27b2249f --- /dev/null +++ b/scripts/postinst @@ -0,0 +1,3 @@ +#!/bin/bash +chmod 4755 /usr/local/bin/pktminerg +chmod 4755 /usr/local/bin/gredump diff --git a/scripts/postinst_rpm.sh b/scripts/postinst_rpm.sh new file mode 100644 index 000000000..a27b2249f --- /dev/null +++ b/scripts/postinst_rpm.sh @@ -0,0 +1,3 @@ +#!/bin/bash +chmod 4755 /usr/local/bin/pktminerg +chmod 4755 /usr/local/bin/gredump diff --git a/scripts/puppet_packet_agent.pp b/scripts/puppet_packet_agent.pp index 114796903..a47bb4b80 100644 --- a/scripts/puppet_packet_agent.pp +++ b/scripts/puppet_packet_agent.pp @@ -3,30 +3,30 @@ 'Suse': { $lib_pcap = 'libpcap'; $cur_dir = '/tmp/'; - $download_link = 'https://github.com/Netis/packet-agent/releases/download/v0.3.3/netis-packet-agent-0.3.4.el6.x86_64.rpm'; + $download_link = 'https://github.com/Netis/packet-agent/releases/download/v0.5.0/netis-packet-agent-0.5.0.el6.x86_64.rpm'; $package_provider = 'rpm'; - $install_file = '/tmp/netis-packet-agent-0.3.4.el6.x86_64.rpm' + $install_file = '/tmp/netis-packet-agent-0.5.0.el6.x86_64.rpm' } 'RedHat': { $lib_pcap = 'libpcap'; $cur_dir = '/tmp/'; - $download_link = 'https://github.com/Netis/packet-agent/releases/download/v0.3.3/netis-packet-agent-0.3.4.el6.x86_64.rpm'; + $download_link = 'https://github.com/Netis/packet-agent/releases/download/v0.5.0/netis-packet-agent-0.5.0.el6.x86_64.rpm'; $package_provider = 'rpm'; - $install_file = '/tmp/netis-packet-agent-0.3.4.el6.x86_64.rpm' + $install_file = '/tmp/netis-packet-agent-0.5.0.el6.x86_64.rpm' } 'Debian': { $lib_pcap = 'libpcap-dev'; $cur_dir = '/tmp/'; - $download_link = 'https://github.com/Netis/packet-agent/releases/download/v0.3.3/netis-packet-agent-0.3.3_amd64.deb'; + $download_link = 'https://github.com/Netis/packet-agent/releases/download/v0.5.0/netis-packet-agent-0.5.0_amd64.deb'; $package_provider = 'dpkg'; - $install_file = '/tmp/netis-packet-agent-0.3.3_amd64.deb' + $install_file = '/tmp/netis-packet-agent-0.5.0_amd64.deb' } default: { $lib_pcap = 'libpcap'; $cur_dir = '/tmp/'; - $download_link = 'https://github.com/Netis/packet-agent/releases/download/v0.3.3/netis-packet-agent-0.3.4.el6.x86_64.rpm'; + $download_link = 'https://github.com/Netis/packet-agent/releases/download/v0.5.0/netis-packet-agent-0.5.0.el6.x86_64.rpm'; $package_provider = 'rpm'; - $install_file = '/tmp/netis-packet-agent-0.3.4.el6.x86_64.rpm' + $install_file = '/tmp/netis-packet-agent-0.5.0.el6.x86_64.rpm' } } @@ -47,4 +47,4 @@ ensure => installed, provider => $package_provider, source => $install_file -} \ No newline at end of file +} diff --git a/scripts/recvzmq.md b/scripts/recvzmq.md new file mode 100644 index 000000000..6e54ab0c4 --- /dev/null +++ b/scripts/recvzmq.md @@ -0,0 +1,39 @@ +# Usage + +## Usage for recvzmq.py +``` +python recvzmq.py [--span_time seconds] -z port_num -t /path/file_template -a 4 +-z or --zmq_port: zmq bind port +-t or --file_template: file template. Examle: /opt/pcap_cache/nic0/%Y%m%d%H%M%S +-s or --span_time: pcap span time interval. Default: 15, Unit: seconds. +-a or --total_workers: total worker process count of recvzmq. Default 1. +-v or --version: version info +-h or --help: help message +``` + +### Paramters + +* zmq_port
+Zeromq bind port to receive message from remote packet agent client. +
+ +* file_template
+File path and file name of output pcap, the file name template will be formatted. +Examle: /opt/pcap_cache/nic0/%Y%m%d%H%M%S +%Y%m%d%H%M%S will be formatted to something like 20200415090530, pcap name will be 20200415090530_2_0.pcap, 20200415090530_2_1.pcap +
+ +* span_time
+Pcap span time interval. Default: 15, Unit: seconds. +
+ +* total_workers
+Total worker process count of recvzmq. Default 1. +Usually, the max capacity for one worker process is 200Mbps. +
+ +### Examples +* Two child process workers +``` +python recvzmq.py -s 15 -z 82 -f /opt/pcap_cache/nic0/%Y%m%d%H%M%S -a 2 +``` diff --git a/scripts/recvzmq/backup_recvlog.sh b/scripts/recvzmq/backup_recvlog.sh new file mode 100644 index 000000000..58bb18679 --- /dev/null +++ b/scripts/recvzmq/backup_recvlog.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +backup_log_and_clear() { + LOG_FILE_NAME=$1 + tar --overwrite -czf ${LOG_FILE_NAME}.tar.gz ${LOG_FILE_NAME} + >${LOG_FILE_NAME} +} + +LOG_FILE=$1 + +while true +do + sleep 86400 + if [ -f "$LOG_FILE" ] + then + backup_log_and_clear $LOG_FILE + fi +done + diff --git a/scripts/recvzmq/recvd.sh b/scripts/recvzmq/recvd.sh new file mode 100644 index 000000000..7e3ff2510 --- /dev/null +++ b/scripts/recvzmq/recvd.sh @@ -0,0 +1,13 @@ +#!/bin/bash +mkdir -p /opt/bpc/var/log +python /usr/local/bin/recvzmq.py -z 82 -s 15 -a 4 -t /opt/pcap_cache/nic0/%Y%m%d%H%M%S 1>>/opt/bpc/var/log/recvzmq.log 2>>/opt/bpc/var/log/recvzmq.err & +RECV_PID=$! + +rm -rf /var/run/recvzmq/recvzmq.pid +sh /usr/local/bin/backup_recvlog.sh /opt/bpc/var/log/recvzmq.log & +BACKUP_PID=$! + +mkdir -p /var/run/recvzmq +echo "$RECV_PID" > /var/run/recvzmq/recvzmq.pid +echo "$BACKUP_PID" >> /var/run/recvzmq/recvzmq.pid + diff --git a/scripts/recvzmq/recvzmq.py b/scripts/recvzmq/recvzmq.py new file mode 100755 index 000000000..0c5a7b141 --- /dev/null +++ b/scripts/recvzmq/recvzmq.py @@ -0,0 +1,558 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from __future__ import print_function +from collections import deque +from multiprocessing import Process +import zmq +import time +import struct +import sys +import os +import getopt +import traceback + +grekey_file_info = None + +def eprint(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + +#Global header for pcap 2.4 +def pcap_global_header(): + return struct.pack("HIHIBB", 0,0,0,0, 0x08, 0x00) + + +def gre_ip_header(length, checksum): + return struct.pack(">BBHHBBBBHII", 0x45, 0, length, 0, 0x40, 0, 0x40, 0x2f, checksum, 0x7F000001, 0x7F000001) + + +def gre_header(keybit): + return struct.pack(">HHI", 0x2000, 0x6558, keybit) + + +def construct_pkt_bytes(ts_sec, ts_usec, caplen, length, keybit, pkt_data_len, pkt_data): + gre_eth_hdr_len = 14 + gre_ip_hdr_len = 20 + gre_hdr_len = 8 + gre_caplen = gre_eth_hdr_len + gre_ip_hdr_len + gre_hdr_len + pkt_data_len + gre_length = gre_caplen + if length > caplen: + gre_length = gre_eth_hdr_len + gre_ip_hdr_len + gre_hdr_len + length + pkt_bytes = b''.join([ + pcap_packet_header(ts_sec, ts_usec, gre_caplen, gre_length), + gre_eth_header(), + gre_ip_header(gre_ip_hdr_len + gre_hdr_len + pkt_data_len, 0xffff), # TODO: handle checksum + gre_header(keybit), + pkt_data + ]) + return pkt_bytes + + +def create_pcap(config, ts_sec, suffix_id): + cur_time = time.localtime(ts_sec) + file_path_str = time.strftime(config["file_template"], cur_time) + file_path = "%s_%d_%d"%(file_path_str, config["total_workers"], suffix_id) + directory = os.path.dirname(file_path) + if not os.path.exists(directory): + os.makedirs(directory) + if os.path.exists(file_path): + os.remove(file_path) + #print("Open new file: %s"%file_path) + pcap_file = open(file_path, 'a+b') + pcap_file.write(pcap_global_header()) + return pcap_file + + +def get_base_ts(ts_sec, span_time): + return (ts_sec // span_time) * span_time + + +def get_pcapfile(config, ts_sec): + pcap_file = None + span_time = config["span_time"] + global grekey_file_info + if grekey_file_info != None: + (suffix_id, pcap_ts, pcap_file) = grekey_file_info + if (ts_sec // span_time) != (pcap_ts // span_time): + pcap_file.close() + file_path = os.path.abspath(pcap_file.name) + target_path = file_path + ".pcap" + #print("Rename file to: %s"%target_path) + os.rename(file_path, target_path) + pcap_file = create_pcap(config, get_base_ts(ts_sec, span_time), suffix_id) + grekey_file_info = (suffix_id, get_base_ts(ts_sec, span_time), pcap_file) + else: + suffix_id = config["base_suffixid"] + pcap_file = create_pcap(config, get_base_ts(ts_sec, span_time), suffix_id) + grekey_file_info = (suffix_id, get_base_ts(ts_sec, span_time), pcap_file) + return pcap_file + +def takeFirst(elem): + return elem[0] + +class BatchPktsHandler(): + + def __init__(self, config): + self.PKT_EVICT_TS_TIMEOUT = 7 + self.PKT_EVICT_INTERVAL = 1 + self.PKT_EVICT_BUFF_SIZE = 2 * 1024*1024 + + self.config = config + self.first_msg_realworld_time = 0 + self.first_pkt_realworld_time = 0 + self.first_pkt_ts_time = 0 + self.last_heartbeat_ts = 0 + self.min_realworld_ts_pkt_ts_diff = 0 + self.new_realworld_ts_pkt_ts_diff = 0 + self.pkt_evict_ts_checkpoint = 0 + self.evict_num = 0 + self.msg_dict = {} + self.evict_pkts_list = [] + self.export_bytearray = bytearray(self.PKT_EVICT_BUFF_SIZE) + self.export_bytearray_pos = 0 + self.total_drop_pkts = 0 + + self.frag_offset = int(self.config["frag_offset"]) + self.frag_offset_roundup = int((self.frag_offset / 2) / 8) * 8 + + self.keybit_ipid_map = {} + self.last_print_timeout_ts = 0 + + + def is_working_busy(self): + return len(self.msg_dict) > self.PKT_EVICT_TS_TIMEOUT + self.PKT_EVICT_INTERVAL + + + def unpack_msgpkts_to_evict(self, message): + header_size = 8 + timeout_drop_pkts = 0 + version, pkt_num, keybit = struct.unpack(">HHI", message[:header_size]) + pkt_pos = header_size + for j in range(pkt_num): + pkt_data_len, ts_sec, ts_usec, caplen, length = struct.unpack(">HIIII", message[pkt_pos:pkt_pos+18]) + pkt_pos += 18 + if ts_sec < self.pkt_evict_ts_checkpoint: + if j == 0 or j + 1 == pkt_num: + if ts_sec > self.last_print_timeout_ts: + print("id: %d, timeout pkt grekey: %d, ts_sec: %d, caplen: %d, length: %d, pkt_num: %d"%( + self.config['base_suffixid'], keybit, ts_sec, caplen, length, pkt_num)) + self.last_print_timeout_ts = ts_sec + if j == 0 and ts_sec + 1 < self.pkt_evict_ts_checkpoint: # hack: rely on pktg msg batch max timeout 1s + timeout_drop_pkts = pkt_num + break + timeout_drop_pkts += 1 + else: + pkt_data = message[pkt_pos : pkt_pos + pkt_data_len] + pkt_info = (ts_sec*1000000 + ts_usec, caplen, length, keybit, pkt_data_len, pkt_data) + self.evict_pkts_list.append(pkt_info) + pkt_pos += pkt_data_len + self.total_drop_pkts += timeout_drop_pkts + return timeout_drop_pkts + + + def construct_pkt_bytes(self, ts_sec, ts_usec, caplen, length, keybit, pkt_data_len, pkt_data): + gre_eth_hdr_len = 14 + gre_ip_hdr_len = 20 + gre_hdr_len = 8 + gre_ip_layer_max_len = 65535 + + if pkt_data_len == 0 and keybit == 0: + heartbeat_data_len = 4 + struct.pack_into("HIHIHI", self.export_bytearray, self.export_bytearray_pos, 0,0,0,0, 0xffff, 0) + self.export_bytearray_pos += gre_eth_hdr_len + heartbeat_data_len + else: + ipid = self.get_ipid_from_map(keybit) + if gre_eth_hdr_len + gre_ip_hdr_len + gre_hdr_len + length > gre_ip_layer_max_len or pkt_data_len > self.frag_offset: + first_frag_pkt_data_len = self.frag_offset_roundup + if pkt_data_len <= self.frag_offset_roundup: + first_frag_pkt_data_len = int(pkt_data_len / 2 / 8) * 8 + first_frag_pkt_data = pkt_data[0:first_frag_pkt_data_len] + self.construct_firstfrag_pkt_bytes(ipid, ts_sec, ts_usec, first_frag_pkt_data_len, first_frag_pkt_data_len, + keybit, first_frag_pkt_data_len, first_frag_pkt_data, is_frag=True) + + last_frag_pkt_data_len = pkt_data_len - first_frag_pkt_data_len + last_frag_pkt_data = pkt_data[first_frag_pkt_data_len:] + self.construct_lastfrag_pkt_bytes(ipid, ts_sec, ts_usec, last_frag_pkt_data_len, last_frag_pkt_data_len, + keybit, first_frag_pkt_data_len, last_frag_pkt_data_len, last_frag_pkt_data) + else: + self.construct_firstfrag_pkt_bytes(ipid, ts_sec, ts_usec, caplen, length, + keybit, pkt_data_len, pkt_data, is_frag=False) + + buff_is_full = False + if self.export_bytearray_pos >= self.PKT_EVICT_BUFF_SIZE - 65636: + buff_is_full = True + return buff_is_full + + def construct_firstfrag_pkt_bytes(self, ipid, ts_sec, ts_usec, caplen, length, keybit, pkt_data_len, pkt_data, is_frag): + gre_eth_hdr_len = 14 + gre_ip_hdr_len = 20 + gre_hdr_len = 8 + eth_ip_gre_len = 42 # gre_eth_hdr_len + gre_ip_hdr_len + gre_hdr_len + checksum = 0xffff + gre_caplen = eth_ip_gre_len + pkt_data_len + gre_length = gre_caplen + if length > caplen: + gre_length = eth_ip_gre_len + length + + frag_and_offset = 0x40 + if is_frag: + frag_and_offset = 0x20 + + struct.pack_into("HIHIBBBBHHBBBBHIIHHI", self.export_bytearray, self.export_bytearray_pos, 0,0,0,0, 0x08, 0x00, + 0x45, 0, gre_ip_hdr_len + gre_hdr_len + pkt_data_len, + ipid, frag_and_offset, 0, 0x40, 0x2f, checksum, keybit, 0x7F000001, + 0x2000, 0x6558, keybit) + self.export_bytearray_pos += eth_ip_gre_len + if pkt_data_len > 0: + struct.pack_into("!%ds"%(pkt_data_len), self.export_bytearray, self.export_bytearray_pos, pkt_data) + self.export_bytearray_pos += pkt_data_len + + + def construct_lastfrag_pkt_bytes(self, ipid, ts_sec, ts_usec, caplen, length, keybit, first_frag_pkt_data_len, pkt_data_len, pkt_data): + gre_eth_hdr_len = 14 + gre_ip_hdr_len = 20 + checksum = 0xffff + gre_caplen = gre_eth_hdr_len + gre_ip_hdr_len + pkt_data_len + gre_length = gre_caplen + if length > caplen: + gre_length = gre_eth_hdr_len + gre_ip_hdr_len + length + + frag_and_offset = (first_frag_pkt_data_len + 8) / 8 # offset + gre 8 bytes + + struct.pack_into("HIHIBB", self.export_bytearray, self.export_bytearray_pos, 0,0,0,0, 0x08, 0x00) + self.export_bytearray_pos += gre_eth_hdr_len + struct.pack_into(">BBHHHBBHII", self.export_bytearray, self.export_bytearray_pos, 0x45, 0, gre_ip_hdr_len + pkt_data_len, + ipid, frag_and_offset, 0x40, 0x2f, checksum, keybit, 0x7F000001) + self.export_bytearray_pos += gre_ip_hdr_len + if pkt_data_len > 0: + struct.pack_into("!%ds"%(pkt_data_len), self.export_bytearray, self.export_bytearray_pos, pkt_data) + self.export_bytearray_pos += pkt_data_len + + + def get_ipid_from_map(self, keybit): + ipid = 0 + if keybit in self.keybit_ipid_map: + ipid = self.keybit_ipid_map[keybit] + ipid = (ipid + 1) % 65535 + self.keybit_ipid_map[keybit] = ipid + return ipid + + + def write_buf_to_pcap(self, pcapfile): + pcapfile.write(self.export_bytearray[:self.export_bytearray_pos]) + self.export_bytearray_pos = 0 + + + def process_data(self, pkts_list): + span_time = self.config["span_time"] + global grekey_file_info + # export to pcap + for p in pkts_list: + (ts_sec_and_usec, caplen, length, keybit, pkt_data_len, pkt_data) = p + ts_sec = ts_sec_and_usec / 1000000 + ts_usec = ts_sec_and_usec % 1000000 + if grekey_file_info != None: + suffix_id, pcap_ts, pcapfile = grekey_file_info + if (ts_sec // span_time) != (pcap_ts // span_time): # need to rotate to new pcap file + self.write_buf_to_pcap(pcapfile) + pcapfile = get_pcapfile(self.config, ts_sec) + else: + pcapfile = get_pcapfile(self.config, ts_sec) + buff_is_full = self.construct_pkt_bytes(ts_sec, ts_usec, caplen, length, keybit, pkt_data_len, pkt_data) + if buff_is_full: + pcapfile = get_pcapfile(self.config, ts_sec) + self.write_buf_to_pcap(pcapfile) + + + def sort_and_export_pkts(self): + self.evict_pkts_list.sort(key=takeFirst) + if self.pkt_evict_ts_checkpoint == 0: + self.pkt_evict_ts_checkpoint = self.first_pkt_ts_time + self.PKT_EVICT_INTERVAL - self.PKT_EVICT_TS_TIMEOUT + else: + self.update_next_checkpoint() + pkts_list = [] + pkts_count = len(self.evict_pkts_list) + lasti = 0 + while lasti < pkts_count: + p = self.evict_pkts_list[lasti] + ts_sec = p[0] / 1000000 + if ts_sec >= self.pkt_evict_ts_checkpoint: + break + lasti += 1 + pkts_list = self.evict_pkts_list[:lasti] + if lasti > 0: + self.evict_pkts_list = self.evict_pkts_list[lasti:] + + export_pkts_count = len(pkts_list) + left_pkts_count = len(self.evict_pkts_list) + if pkts_list: + self.process_data(pkts_list) + return export_pkts_count, left_pkts_count + + + def get_next_checkpoint(self): + ts_advance = 0 + if self.new_realworld_ts_pkt_ts_diff < self.min_realworld_ts_pkt_ts_diff: + ts_advance = self.min_realworld_ts_pkt_ts_diff - self.new_realworld_ts_pkt_ts_diff + return self.pkt_evict_ts_checkpoint + self.PKT_EVICT_INTERVAL + ts_advance + + + def update_next_checkpoint(self): + self.pkt_evict_ts_checkpoint = self.get_next_checkpoint() + if self.new_realworld_ts_pkt_ts_diff < self.min_realworld_ts_pkt_ts_diff: + print("id: %d, new min realworld pkt ts diff: %ds"%(self.config['base_suffixid'], self.new_realworld_ts_pkt_ts_diff)) + self.min_realworld_ts_pkt_ts_diff = self.new_realworld_ts_pkt_ts_diff + + + def evict_pkts(self, realworld_time_sec_and_usec, fqueue_full_drop): + self.evict_num += 1 + if self.first_pkt_ts_time == 0: + return + timeout_drop_pkts = 0 + evicted_msg_count = 0 + total_msg_count = 0 + to_del_ts = [] + next_checkpoint = self.get_next_checkpoint() + for ts, msg_list in self.msg_dict.items(): + total_msg_count += len(msg_list) + if ts < next_checkpoint: + evicted_msg_count += len(msg_list) + for msg in msg_list: + timeout_drop_pkts += self.unpack_msgpkts_to_evict(msg) + to_del_ts.append(ts) + for ts in to_del_ts: + del self.msg_dict[ts] + self.gen_heartbeat() + export_pkts_count, left_pkts_count = self.sort_and_export_pkts() + now = time.time() + nowstr = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(now)) + print("[%s] id: %d, used: %.2fs, msg %d/%d: %d/%d evicted, export/leftPkts: %d/%d, timeout/frontq/totalDropPkts: %d/%d/%d"%( + nowstr, self.config["base_suffixid"], now - realworld_time_sec_and_usec, evicted_msg_count, total_msg_count, len(to_del_ts), len(to_del_ts) + len(self.msg_dict), + export_pkts_count, left_pkts_count, timeout_drop_pkts, fqueue_full_drop, self.total_drop_pkts)) + sys.stdout.flush() + + + def gen_heartbeat(self): + if self.first_pkt_ts_time != 0: + if self.last_heartbeat_ts == 0: + self.last_heartbeat_ts = self.first_pkt_ts_time + next_checkpoint = self.get_next_checkpoint() + while self.last_heartbeat_ts < next_checkpoint: + self.last_heartbeat_ts += 1 + pkt_info = (self.last_heartbeat_ts*1000000, 0, 0, 0, 0, []) + self.evict_pkts_list.append(pkt_info) + + + def parse_messages(self, messages): + header_size = 8 + realworld_time_sec_and_usec = time.time() + realworld_time = int(realworld_time_sec_and_usec) + if self.first_msg_realworld_time == 0: + self.first_msg_realworld_time = realworld_time + fqueue_full_drop = 0 + if messages: + for message in messages: + version, pkt_num, keybit = struct.unpack(">HHI", message[:header_size]) + if version != 1: + return + pkt_pos = header_size + if pkt_num > 0: + pkt_data_len, pkt_ts_time = struct.unpack(">HI", message[pkt_pos:pkt_pos+6]) + if self.first_pkt_ts_time == 0: + self.first_pkt_realworld_time = realworld_time + self.first_pkt_ts_time = pkt_ts_time + self.min_realworld_ts_pkt_ts_diff = realworld_time - pkt_ts_time + print("first_pkt_realworld_time: %d, first_pkt_ts_time: %d, diff: %ds"%(realworld_time, self.first_pkt_ts_time, self.min_realworld_ts_pkt_ts_diff)) + self.new_realworld_ts_pkt_ts_diff = realworld_time - pkt_ts_time + if pkt_ts_time in self.msg_dict: + self.msg_dict[pkt_ts_time].append(message) + else: + if len(self.msg_dict) > self.PKT_EVICT_TS_TIMEOUT + self.PKT_EVICT_INTERVAL + 20: + fqueue_full_drop += pkt_num + self.total_drop_pkts += pkt_num + else: + self.msg_dict[pkt_ts_time] = [message] + if realworld_time >= self.first_msg_realworld_time + self.PKT_EVICT_INTERVAL * (self.evict_num + 1): + self.evict_pkts(realworld_time_sec_and_usec, fqueue_full_drop) + + +def recv_msg_to_parse(batch_pkts_handler, socket): + messages = [] + try: + while True: + message = socket.recv(flags=zmq.NOBLOCK) + messages.append(message) + except zmq.error.Again as _e: + if not messages and not batch_pkts_handler.is_working_busy(): + time.sleep(0.01) + batch_pkts_handler.parse_messages(messages) + +def server_loop_imp(config): + context = zmq.Context() + socket = context.socket(zmq.PULL) + socket.setsockopt(zmq.RCVTIMEO, 1000) + socket.setsockopt(zmq.RCVHWM, 2000 * 1000) + socket.setsockopt(zmq.SNDHWM, 2000 * 1000) + if config["total_workers"] == 1: + socket.bind("tcp://*:%d"%(config["zmq_port"])) + else: + socket.connect("tcp://127.0.0.1:%d"%(config["zmq_port"])) + batch_pkts_handler = BatchPktsHandler(config) + while True: + try: + recv_msg_to_parse(batch_pkts_handler, socket) + except KeyboardInterrupt: + eprint("KeyboardInterrupt") + raise + except Exception as e: + eprint(e) + track = traceback.format_exc() + eprint(track) + raise + except struct.error as se: + eprint(se) + except: + eprint("Unexpected error") + raise + + +def server_loop(port, file_template, span_time, total_workers, frag_offset, base_suffixid): + config = { "zmq_port": port, "file_template": file_template, "span_time": span_time, + "total_workers": total_workers, "frag_offset": frag_offset, "base_suffixid": base_suffixid } + server_loop_imp(config) + + +def check_need_terminate(workers): + need_term = False + for w in workers: + if not w.is_alive(): + need_term = True + if need_term: + eprint("Fatal error: at least one worker process exited") + for w in workers: + if w.is_alive(): + w.terminate() + sys.exit(-1) + + +def dispatch_loop(config): + context = zmq.Context() + front_socket = context.socket(zmq.PULL) + front_socket.setsockopt(zmq.RCVTIMEO, 1000) + front_socket.setsockopt(zmq.RCVHWM, 2000 * 1000) + front_socket.setsockopt(zmq.SNDHWM, 2000 * 1000) + front_socket.bind("tcp://*:%d"%(config["zmq_port"])) + + backend_port = config["zmq_port"] + 1 + backend_socket = context.socket(zmq.PUSH) + backend_socket.setsockopt(zmq.SNDTIMEO, 1000) + backend_socket.setsockopt(zmq.RCVHWM, 2000 * 1000) + backend_socket.setsockopt(zmq.SNDHWM, 2000 * 1000) + backend_socket.bind("tcp://127.0.0.1:%d"%(backend_port)) + workers = [] + for i in range(config["total_workers"]): + w = Process(target=server_loop, args=(backend_port, config["file_template"], config["span_time"], config["total_workers"], config["frag_offset"], i)) + workers.append(w) + w.start() + + while True: + try: + message = None + try: + message = front_socket.recv() + except zmq.error.Again: + check_need_terminate(workers) + if message is None: + continue + while True: + try: + backend_socket.send(message) + except zmq.error.Again as _e: + check_need_terminate(workers) + break + except KeyboardInterrupt: + eprint("KeyboardInterrupt") + raise + except Exception as e: + eprint(e) + track = traceback.format_exc() + eprint(track) + raise + except: + eprint("Unexpected error") + raise + + +def usage(): + print( +"""Usage: +python recvzmq.py [--span_time seconds] -z port_num -t /path/file_template +-z or --zmq_port:\tzmq bind port +-t or --file_template:\tfile template. Examle: /opt/pcap_cache/nic0/%Y%m%d%H%M%S +-s or --span_time:\tpcap span time interval. Default: 15, Unit: seconds. +-a or --total_workers:\ttotal worker process count of recvzmq. Default 1. +-g or --frag_offset:\tspecify ip fragment offset( <= 65535). Default 64000 +-v or --version:\tversion info +-h or --help:\t\thelp message +""") + + +def parse_args(cfg_dict): + if len(sys.argv) == 1: + usage() + sys.exit() + try: + options, args = getopt.getopt(sys.argv[1:], "hvz:t:s:a:b:g:", + ["help", "version", "zmq_port=", "file_template=", "span_time=", "total_workers=", "base_suffixid=", "frag_offset="]) + except getopt.GetoptError as e: + eprint(e) + sys.exit(-1) + + for name, value in options: + if name in ("-h", "--help"): + usage() + sys.exit() + elif name in ("-v", "--version"): + print('recvzmq version 1.3.0') + sys.exit() + elif name in ("-z", "--zmq_port"): + cfg_dict["zmq_port"] = int(value) + elif name in ("-t", "--file_template"): + cfg_dict["file_template"] = value + elif name in ("-s", "--span_time"): + cfg_dict["span_time"] = int(value) + elif name in ("-a", "--total_workers"): + cfg_dict["total_workers"] = int(value) + elif name in ("-b", "--base_suffixid"): + cfg_dict["base_suffixid"] = int(value) + elif name in ("-g", "--frag_offset"): + cfg_dict["frag_offset"] = 65535 if int(value) > 65535 else int(value) + if "zmq_port" not in cfg_dict: + eprint("require param: -z zmq_port") + sys.exit(-1) + if "file_template" not in cfg_dict: + eprint("require param: -t /path/file_template/%Y%m%d/%Y%m%d%H/%Y%m%d%H%M%S") + sys.exit(-1) + +config = {"span_time": 15, "total_workers": 1, "base_suffixid": 0, "frag_offset": 64000} +parse_args(config) +if config["total_workers"] == 1: + server_loop_imp(config) +else: + dispatch_loop(config) + diff --git a/scripts/recvzmq/recvzmq.service b/scripts/recvzmq/recvzmq.service new file mode 100644 index 000000000..e880365d2 --- /dev/null +++ b/scripts/recvzmq/recvzmq.service @@ -0,0 +1,17 @@ +[Unit] +Description=Receive PktgZmq Service +After=network.target network-online.target + +[Service] +Type=forking +KillMode=control-group +Restart=always +RestartSec=3 +ExecStart=/bin/bash /usr/local/etc/recvd.sh +ExecStartPre=/bin/mkdir -p /var/run/recvzmq +ExecStartPre=/bin/chmod 0777 /var/run/recvzmq +PIDFile=/var/run/recvzmq/recvzmq.pid +PrivateTmp=true + +[Install] +WantedBy=multi-user.target diff --git a/scripts/recvzmq_installer.sh b/scripts/recvzmq_installer.sh new file mode 100644 index 000000000..a1b01db82 --- /dev/null +++ b/scripts/recvzmq_installer.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +RECV_TAR_GZ=$1 +MAJOR_VERSION=0 +if [ -e /etc/centos-release ]; then + MAJOR_VERSION=`rpm -q --queryformat '%{VERSION}' centos-release` +fi + +Usage() { + echo "Usage:" + echo " sh recvzmq_installer.sh " + echo ":" + echo " path to recvzmq.tar.gz which include recvzmq.py, recvzmq.service etc..." + echo "Example:" + echo " sh recvzmq_installer.sh /path/to/recvzmq.tar.gz" +} + +if [[ -z "$RECV_TAR_GZ" ]]; then + Usage + exit 1 +fi + + +install_recvzmq() { + \cp -rf recvzmq_installer/recvzmq.py /usr/local/bin/recvzmq.py + \cp -rf recvzmq_installer/backup_recvlog.sh /usr/local/bin/backup_recvlog.sh + \cp -rf recvzmq_installer/recvd.sh /usr/local/etc/recvd.sh + if [ $MAJOR_VERSION = "6" ]; then + echo "sh /usr/local/etc/recvd.sh &" >> /etc/rc.d/rc.local + elif [ $MAJOR_VERSION = "7" ]; then + \cp -rf recvzmq_installer/recvzmq.service /etc/systemd/system/recvzmq.service + fi + + echo "Install finished" +} + + +install_pyzmq() { + if [ $MAJOR_VERSION = "6" ]; then + rpm -ivh recvzmq_installer/pyzmq-el6/openpgm-5.1.118-3.el6.x86_64.rpm + rpm -ivh recvzmq_installer/pyzmq-el6/zeromq3-3.2.5-1.el6.x86_64.rpm + rpm -ivh recvzmq_installer/pyzmq-el6/python-zmq-14.3.1-1.el6.x86_64.rpm + elif [ $MAJOR_VERSION = "7" ]; then + rpm -ivh recvzmq_installer/pyzmq-el7/libsodium-1.0.18-1.el7.x86_64.rpm + rpm -ivh recvzmq_installer/pyzmq-el7/openpgm-5.2.122-2.el7.x86_64.rpm + rpm -ivh recvzmq_installer/pyzmq-el7/zeromq-4.1.4-6.el7.x86_64.rpm + rpm -ivh recvzmq_installer/pyzmq-el7/python2-zmq-14.7.0-11.el7.x86_64.rpm + else + echo "Unsupported version: $MAJOR_VERSION" + exit 1 + fi +} + + +mkdir -p recvzmq_installer +tar -xvf $RECV_TAR_GZ --strip-components 1 -C recvzmq_installer/ + +install_pyzmq +install_recvzmq + +rm -rf recvzmq_installer + diff --git a/scripts/test_pap_perf.sh b/scripts/test_pap_perf.sh new file mode 100755 index 000000000..17a4b05af --- /dev/null +++ b/scripts/test_pap_perf.sh @@ -0,0 +1,164 @@ +#!/bin/sh + +SHELL_FOLDER=`pwd` +MAJOR_VERSION=0 +if [ -e /etc/centos-release ]; then + MAJOR_VERSION=`rpm -q --queryformat '%{VERSION}' centos-release` +fi + + +prepare_iperf() { + cd $SHELL_FOLDER + if [ -e iperf_installed.txt ]; then + echo "assume iperf installed" + else + yum -y install iperf psmisc + echo 1 > iperf_installed.txt + fi +} + +cgroup_iperf() { + if [ $MAJOR_VERSION = "6" ]; then + cd /cgroup/cpuset + else + cd /sys/fs/cgroup/cpuset + fi + mkdir -p iperf + cd iperf + + echo 0 > cpuset.cpus + echo 0 > cpuset.mems + + for pid in `ps -ef | grep iperf | grep -v grep | awk '{print $2}'` ; do echo $pid > cgroup.procs; done +} + +cgroup_pktg() { + CPU_IDS=$1 + if [ $MAJOR_VERSION = "6" ]; then + cd /cgroup/cpuset + else + cd /sys/fs/cgroup/cpuset + fi + mkdir -p pktg + cd pktg + + echo $CPU_IDS > cpuset.cpus + echo 0 > cpuset.mems + + for pid in `ps -ef | grep pktminerg | grep -v grep | awk '{print $2}'` ; do echo $pid > cgroup.procs; done +} + +replay() { + cd $SHELL_FOLDER + IPERF_IP=$1 + IPERF_PORT=$2 + BPS=$3 + DURATION_S=$4 + STATS_TXT=stats-${IPERF_IP}-${IPERF_PORT}.txt + + echo "------------------------------------" >> stats.txt + echo "`date`" >> stats.txt + echo "Send to $IPERF_IP:$IPERF_PORT $BPS Mbps, $DURATION_S seconds" >> stats.txt + echo "iperf -c $IPERF_IP -p $IPERF_PORT -i 10 -t $DURATION_S -w 20K -m -b ${BPS}M -l 1406 -M 1406 -N" >> stats.txt + + echo "------------------------------------" >> $STATS_TXT + echo "`date`" >> $STATS_TXT + echo "Send to $IPERF_IP:$IPERF_PORT $BPS Mbps, $DURATION_S seconds" >> $STATS_TXT + echo "iperf -c $IPERF_IP -p $IPERF_PORT -i 10 -t $DURATION_S -w 20K -m -b ${BPS}M -l 1406 -M 1406 -N" >> $STATS_TXT + + #python /root/fake_iperf.py $DURATION_S & + iperf -c $IPERF_IP -p $IPERF_PORT -i 60 -t $DURATION_S -w 20K -m -b ${BPS}M -l 1406 -M 1406 -N >> $STATS_TXT & +} + +run_pktg() { + cd $SHELL_FOLDER + NIC=$1 + GRE_IP=$2 + GRE_KEYBIT=$3 + CPU_ID=$4 + echo "====================================" >> stats.txt + echo "`date`" >> stats.txt + echo "pktminerg -i $NIC -r $GRE_IP -k $GRE_KEYBIT -p --cpu $CPU_ID" >> stats.txt + + echo "====================================" >> pktg.txt + echo "`date`" >> pktg.txt + echo "pktminerg -i $NIC -r $GRE_IP -k $GRE_KEYBIT -p --cpu $CPU_ID" >> pktg.txt + pktminerg -i $NIC -r $GRE_IP -k $GRE_KEYBIT -p --cpu $CPU_ID -b 50 >> pktg.txt & +} + +stats() { + cd $SHELL_FOLDER + for (( j=1; j<=10000000; j++ )) + do + echo "`ps aux | grep pktminerg | grep -v grep`" >> stats.txt + echo "`sar -n DEV 5 1 | grep Average.*eth | grep -v grep`" >> stats.txt + sleep 10 + COUNT=`ps aux | grep iperf | grep -v grep | wc -l` + if [ "$COUNT" -ge "1" ] + then + sleep 1 + else + break + fi + done + sleep 1 + echo "------------------------------------" >> stats.txt +} + +pktg_test_case() { + IPERF_IP=$1 + IPERF_PORT=$2 + BPS=$3 + DURATION_S=$4 + REPLAY_ETH=$5 + GRE_RECV_IP=$6 + GRE_KEYBIT=$7 + PKTG_CPU_ID=$8 + + echo "BPS: $BPS Mbps" + + echo "BPS: $BPS Mbps" >> pktg.txt + run_pktg $REPLAY_ETH $GRE_RECV_IP $GRE_KEYBIT $PKTG_CPU_ID + replay $IPERF_IP $IPERF_PORT $BPS $DURATION_S + #replay 10.1.3.199 81 $BPS $DURATION_S + #replay 10.1.3.199 81 $BPS $DURATION_S + stats + + killall pktminerg +} + +main_test() { + IPERF_IP=$1 + IPERF_PORT=$2 + DURATION_S=$3 + REPLAY_ETH=$4 + GRE_RECV_IP=$5 + GRE_KEYBIT=$6 + PKTG_CPU_ID=$7 + + for (( k=10; k<=100; k++ )) + do + pktg_test_case $1 $2 $k $3 $4 $5 $6 $7 + done +} + + + +if [ "$#" -ne 7 ]; then + echo "Usage:" + echo " sh test_pktg_perf.sh iperf_ip iperf_port duration_s replay_nic gre_recv_ip gre_keybit pktg_cpu_id" + echo " iperf_ip: iperf server IP to simulate network traffic" + echo " iperf_port: iperf server port to simulate network traffic" + echo " duration_s: duration seconds of each test case" + echo " replay_nic: tcpreplay target network interface(eth1, eth2...)." + echo " gre_recv_ip: remote ip to receive gre packet." + echo " grep_keybit: gre keybit" + echo " pktg_cpu_id: limit pktminerg to run on this cpu processor id (suggest to NOT use core 0)." + echo "Example:" + echo " sh test_pktg_perf.sh 10.1.3.99 81 300 eth2 192.168.0.1 128 1" +else + prepare_iperf + echo "main_test" + main_test $1 $2 $3 $4 $5 $6 $7 +fi + diff --git a/src/agent_control_itf.h b/src/agent_control_itf.h new file mode 100644 index 000000000..354be8ef6 --- /dev/null +++ b/src/agent_control_itf.h @@ -0,0 +1,49 @@ +#ifndef SRC_CONTROL_ITF_H_ +#define SRC_CONTROL_ITF_H_ + + +#define MAX_MSG_CONTENT_LENGTH (256) +#define MSG_MAGIC_NUMBER (0x504D3230) +#define MSG_HEADER_LENGTH (16) + +// request and response data format, between zmq client and server + +/* message struction, reference doc/msg.md */ +typedef struct msg { + /* header */ + uint32_t magic; // must be 0x50 0x4D 0x32 0x30 in order. + uint32_t msglength; // msg length, include header, in bytes. + uint32_t action; // list below + uint32_t query_id; // the query id to identify each client for req flush + + /* body */ + char body[MAX_MSG_CONTENT_LENGTH]; +} __attribute__((packed)) msg_t, * msg_ptr_t; + + +// support action now +typedef enum msg_action_req_type { + MSG_ACTION_REQ_INVALID = 0x0000, + MSG_ACTION_REQ_QUERY_STATUS = 0x0001, + MSG_ACTION_REQ_MAX +} msg_act_req_type_e; + +// action MSG_ACTION_REQ_QUERY_STATUS's response data body. +typedef struct msg_status { + uint32_t ver; + uint32_t start_time; + uint32_t last_time; + uint32_t total_cap_bytes; + uint32_t total_cap_packets; + uint32_t total_cap_drop_count; + uint32_t total_filter_drop_count; + uint32_t total_fwd_drop_count; +}__attribute__((packed)) msg_status_t, * msg_status_ptr_t; + + + + + +#endif + + diff --git a/src/agent_control_plane.cpp b/src/agent_control_plane.cpp new file mode 100644 index 000000000..c481e8002 --- /dev/null +++ b/src/agent_control_plane.cpp @@ -0,0 +1,189 @@ + +#include +#include +#include +#include +#include + +#include "agent_status.h" +#include "agent_control_plane.h" + + +AgentControlPlane::AgentControlPlane():_zmq_port(DEFAULT_ZMQ_SERVER_PORT), + _zmq_context(DEFAULT_ZMQ_IO_THREAD), _zmq_socket(_zmq_context, ZMQ_REP), _tid(0) { + +} + +AgentControlPlane::AgentControlPlane(int zmq_port):_zmq_port(zmq_port), + _zmq_context(DEFAULT_ZMQ_IO_THREAD), _zmq_socket(_zmq_context, ZMQ_REP), _tid(0) { + +} + +AgentControlPlane::~AgentControlPlane() { + if (_tid != 0) { + close_msg_server(); + } + _tid = 0; +} + + + +int AgentControlPlane::init_msg_server() { + + int32_t err = pthread_attr_init(&_attr); + if (err != 0) { + std::cerr << "[pktminerg] pthread_attr_init failed" << std::endl; + return 1; + } + + err = pthread_attr_setdetachstate(&_attr, PTHREAD_CREATE_DETACHED); + if (0 == err) { + err = pthread_create(&_tid, &_attr, run, (void*)this); + if (err) { + std::cerr << "[pktminerg] pthread_create failed" << std::endl; + } + } + pthread_attr_destroy(&_attr); + std::cout << "[pktminerg] daemon zmq server init fnished. tid = " << _tid << std::endl; + + return 0; +} + +int AgentControlPlane::close_msg_server() { + if (pthread_cancel(_tid)) { + std::cerr << "[pktminerg] pthread_cancel failed" << std::endl; + } + _tid = 0; + return 0; +} + + +void* AgentControlPlane::run(void* inst) { + if (!inst) { + std::cerr << "[pktminerg] msg server routine: void handle" << std::endl; + return nullptr; + } + AgentControlPlane* serv = static_cast(inst); + + char zmq_addr[32] = "tcp://*:"; + std::string port = std::to_string(serv->_zmq_port); + serv->_zmq_socket.bind(std::strcat(zmq_addr, port.c_str())); + + char recv_string[sizeof(msg_t)]; + msg_t pkt_req_msg, pkt_res_msg; + + pthread_cleanup_push(on_destroy, inst); + + while (true) { + pthread_testcancel(); + + memset(&pkt_req_msg, 0, sizeof(msg_t)); + memset(&pkt_res_msg, 0, sizeof(msg_t)); + memset(recv_string, 0, sizeof(msg_t)); + + zmq::message_t msg_recv; + zmq::recv_result_t recv_ret = {}; + recv_ret = serv->_zmq_socket.recv(msg_recv, zmq::recv_flags::dontwait); + if (!recv_ret) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + continue; + } + + size_t zmq_recv_size = msg_recv.size(); + if (zmq_recv_size <= sizeof(recv_string)) { + memcpy(recv_string, msg_recv.data(), zmq_recv_size); + } + + serv->msg_req_process(recv_string, zmq_recv_size, &pkt_req_msg); + serv->msg_rsp_process(&pkt_req_msg, &pkt_res_msg); + + // Send Response + zmq::send_result_t send_ret = {}; + zmq::message_t msg_send(&pkt_res_msg, sizeof(msg_t), NULL); + send_ret = serv->_zmq_socket.send(msg_send, zmq::send_flags::none); + + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + + + pthread_cleanup_pop(0); + pthread_exit((void*) 0); + return nullptr; +} + + + + +void AgentControlPlane::on_destroy(void* inst) { + +} + + + +int AgentControlPlane::msg_req_process(const char* buf, size_t size, msg_t* req_msg) { + /* check size */ + if (size > (sizeof(msg_t))) { + std::cerr << "[pktminerg] Err, too long msg size:" << size << std::endl; + return -1; + } + + /* construct msg */ + memcpy(req_msg, buf, size); + + if (size < (sizeof(msg_t) - MAX_MSG_CONTENT_LENGTH)) { + std::cerr << "[pktminerg] Err, invalid msg size:" << size << std::endl; + return -1; + } + + /* check magic */ + if (req_msg->magic != MSG_MAGIC_NUMBER) { + std::cerr << "[pktminerg] Err, invalid msg magic number:" << req_msg->magic << std::endl; + return -1; + } + + /* check action */ + if (req_msg->action >= MSG_ACTION_REQ_MAX) { + std::cerr << "[pktminerg] Err, invalid action request:" << req_msg->action << std::endl; + return -1; + } + return 0; +} + + + +int AgentControlPlane::msg_rsp_process(const msg_t* req_msg, msg_t* res_msg) { + if (req_msg->action == MSG_ACTION_REQ_QUERY_STATUS) { + res_msg->magic = req_msg->magic; + res_msg->action = req_msg->action; + res_msg->query_id = req_msg->query_id; + res_msg->msglength = MSG_HEADER_LENGTH + sizeof(msg_status_t); + msg_status_t stat; + msg_rsp_process_get_status(&stat); + memcpy(res_msg->body, &stat, sizeof(msg_status_t)); + } + return 0; +} + + +int AgentControlPlane::msg_rsp_process_get_status(msg_status_t* p_stat) { + + memset(p_stat, 0, sizeof(msg_status_t)); + p_stat->ver = MSG_SERVER_VERSION; + AgentStatus* inst = AgentStatus::get_instance(); + if (!inst) { + return -1; + } + + p_stat->start_time = static_cast(inst->first_packet_time()); + p_stat->last_time = static_cast(inst->last_packet_time()); + p_stat->total_cap_bytes = static_cast(inst->total_cap_bytes()); + p_stat->total_cap_packets = static_cast(inst->total_cap_packets()); + p_stat->total_cap_drop_count = static_cast(inst->total_cap_drop_count()); + p_stat->total_filter_drop_count = static_cast(inst->total_filter_drop_count()); + p_stat->total_fwd_drop_count = static_cast(inst->total_fwd_drop_count()); + return 0; +} + + + + diff --git a/src/agent_control_plane.h b/src/agent_control_plane.h new file mode 100644 index 000000000..776779d1d --- /dev/null +++ b/src/agent_control_plane.h @@ -0,0 +1,54 @@ +#ifndef SRC_MSGSERVER_H_ +#define SRC_MSGSERVER_H_ + + +#include + +#include +#include "zmq.hpp" + +#include "agent_control_itf.h" + +class AgentControlPlane { + +public: + AgentControlPlane(); + AgentControlPlane(int zmq_port); + ~AgentControlPlane(); + + int init_msg_server(); + int close_msg_server(); + + +public: + const static int DEFAULT_ZMQ_IO_THREAD = 16; + const static int DEFAULT_ZMQ_SERVER_PORT = 5556; + + const static uint32_t MSG_SERVER_VERSION = 0x01; + +private: + int msg_req_process(const char* buf, size_t size, msg_t* req_msg); + int msg_rsp_process(const msg_t* req_msg, msg_t* res_msg); + int msg_rsp_process_get_status(msg_status_t* stat); + +private: + static void* run(void*); + static void on_destroy(void*); + +private: + // zmq + int _zmq_port; + zmq::context_t _zmq_context; + zmq::socket_t _zmq_socket; + + // pthread + pthread_attr_t _attr; + pthread_t _tid; + // std::thread _msg_server_loop; +}; + + + +#endif + + diff --git a/src/agent_status.cpp b/src/agent_status.cpp new file mode 100644 index 000000000..78c572ab0 --- /dev/null +++ b/src/agent_status.cpp @@ -0,0 +1,65 @@ + +#include "agent_status.h" + +AgentStatus::AgentStatus() { + _drop_count_at_beginning = 0; + + _first_packet_time = 0; + _last_packet_time = 0; + + _total_cap_bytes = 0; + _total_cap_packets = 0; + _total_cap_drop_count = 0; + + _total_filter_drop_count = 0; + _total_fwd_drop_count = 0; +} + +AgentStatus::~AgentStatus() { + +} + +int AgentStatus::reset_agent_status() { + _drop_count_at_beginning = 0; + + _first_packet_time = 0; + _last_packet_time = 0; + + _total_cap_bytes = 0; + _total_cap_packets = 0; + _total_cap_drop_count = 0; + + _total_filter_drop_count = 0; + _total_fwd_drop_count = 0; + return 0; +} + + +int AgentStatus::update_capture_status(uint64_t cur_pkt_time, uint32_t cur_pkt_caplen, + uint64_t total_fwd_count, uint64_t total_fwd_drop_count, pcap_t* handle){ + if(_first_packet_time == 0) { + _first_packet_time = cur_pkt_time; + + struct pcap_stat stat; + if(handle != NULL && pcap_stats(handle, &stat) == 0) { + _drop_count_at_beginning = stat.ps_drop + stat.ps_ifdrop; + } + } + _last_packet_time = cur_pkt_time; + + _total_cap_bytes += cur_pkt_caplen; + + struct pcap_stat stat; + if (handle != NULL && pcap_stats(handle, &stat) == 0) { + _total_cap_packets = stat.ps_recv; + _total_cap_drop_count = stat.ps_drop + stat.ps_ifdrop; + _total_cap_drop_count -= _drop_count_at_beginning; + } + + _total_fwd_drop_count = total_fwd_drop_count; + _total_filter_drop_count = 0; //_total_cap_packets - total_fwd_count - _total_fwd_drop_count; + + return 0; +} + + diff --git a/src/agent_status.h b/src/agent_status.h new file mode 100644 index 000000000..f6f7a8758 --- /dev/null +++ b/src/agent_status.h @@ -0,0 +1,54 @@ +#ifndef SRC_AGENT_STATUS_H_ +#define SRC_AGENT_STATUS_H_ + + +#include + +#include + + + +class AgentStatus { +public: + AgentStatus(); + ~AgentStatus(); + +public: + static AgentStatus* get_instance() { + static AgentStatus inst; + return &inst; + } + +public: + int update_capture_status(uint64_t cur_pkt_time, uint32_t cur_pkt_caplen, + uint64_t total_fwd_count, uint64_t total_fwd_drop_count, pcap_t* handle = NULL); + int reset_agent_status(); + + +public: + uint64_t first_packet_time() { return _first_packet_time; } + uint64_t last_packet_time() { return _last_packet_time; } + uint64_t total_cap_bytes() { return _total_cap_bytes; } + uint64_t total_cap_packets() { return _total_cap_packets; } + uint64_t total_cap_drop_count() { return _total_cap_drop_count; } + uint64_t total_filter_drop_count() { return _total_filter_drop_count; } + uint64_t total_fwd_drop_count() { return _total_fwd_drop_count; } + + +private: + + // packet agent metrics + uint64_t _drop_count_at_beginning; + + std::atomic _first_packet_time; + std::atomic _last_packet_time; + std::atomic _total_cap_bytes; + std::atomic _total_cap_packets; + std::atomic _total_cap_drop_count; + std::atomic _total_filter_drop_count; + std::atomic _total_fwd_drop_count; +}; + +#endif + + diff --git a/src/pcapexport.h b/src/pcapexport.h index 00c6a324b..694f1cc70 100644 --- a/src/pcapexport.h +++ b/src/pcapexport.h @@ -3,9 +3,16 @@ #include +#define PKTD_UNKNOWN -1 +#define PKTD_IC 1 +#define PKTD_OG 2 +#define PKTD_NONCHECK 0 + enum class exporttype : uint8_t { gre = 0, file = 1, + zmq = 2, + vxlan = 3 }; class PcapExportBase { @@ -16,7 +23,7 @@ class PcapExportBase { return _type; } virtual int initExport() = 0; - virtual int exportPacket(const struct pcap_pkthdr *header, const uint8_t *pkt_data) = 0; + virtual int exportPacket(const struct pcap_pkthdr *header, const uint8_t *pkt_data, int direct) = 0; virtual int closeExport() = 0; }; diff --git a/src/pcaphandler.cpp b/src/pcaphandler.cpp index 317e4912a..009ee0438 100644 --- a/src/pcaphandler.cpp +++ b/src/pcaphandler.cpp @@ -1,8 +1,17 @@ -#include "pcaphandler.h" #include #include #include +#include +#include +#include +#include +#include +#include + +#include "pcaphandler.h" #include "scopeguard.h" +#include "agent_status.h" +#include "vlan.h" PcapHandler::PcapHandler(std::string dumpDir, int16_t dumpInterval): _dumpDir(dumpDir), @@ -11,12 +20,14 @@ PcapHandler::PcapHandler(std::string dumpDir, int16_t dumpInterval): _gre_drop_count = 0; _pcap_handle = NULL; _pcap_dumpter = NULL; + if (dumpInterval != -1) { _dumpDir = dumpDir + "/"; _timeStamp = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); if(!boost::filesystem::is_directory(_dumpDir)) boost::filesystem::create_directories(_dumpDir); } + std::memset(_errbuf, 0, sizeof(_errbuf)); } @@ -66,12 +77,46 @@ void PcapHandler::closePcap() { } void PcapHandler::packetHandler(const struct pcap_pkthdr* header, const uint8_t* pkt_data) { + ether_header* eth; + iphdr* ip; + ip6_hdr* ipv6; + uint16_t eth_type; + int direct; + vlan_tag *vlan_hdr; + + if(header->caplen < sizeof(ether_header)) + return; + eth = (ether_header*)pkt_data; + eth_type = ntohs(eth->ether_type); + direct = PKTD_UNKNOWN; + + switch(eth_type) { + case ETHERTYPE_IP: + ip = (iphdr*)(pkt_data + sizeof(ether_header)); + direct = checkPktDirectionV4((const in_addr*)&ip->saddr, (const in_addr*)&ip->daddr); + break; + case ETHERTYPE_IPV6: + ipv6 = (ip6_hdr*)(pkt_data + sizeof(ether_header)); + direct = checkPktDirectionV6(&ipv6->ip6_src, &ipv6->ip6_dst); + break; + + case ETHERTYPE_VLAN: { + vlan_hdr = (vlan_tag *) (pkt_data + sizeof(ether_header)); + uint16_t vlan_type = ntohs(vlan_hdr->vlan_tci); + switch (vlan_type) { + case ETHERTYPE_IP: + ip = (iphdr *) (pkt_data + sizeof(ether_header) + sizeof(vlan_tag)); + direct = checkPktDirectionV4((const in_addr *) &ip->saddr, (const in_addr *) &ip->daddr); + break; + } + } + default: + break; + } + std::for_each(_exports.begin(), _exports.end(), - [header, pkt_data, this](std::shared_ptr pcapExport) { -// if (header->caplen > 1472) { -// std::cout << "pkt " << _gre_count << ", len: " << header->len << ", caplen: " << header->caplen << std::endl; -// } - int ret = pcapExport->exportPacket(header, pkt_data); + [header, pkt_data, this, direct](std::shared_ptr pcapExport) { + int ret = pcapExport->exportPacket(header, pkt_data, direct); if (pcapExport->getExportType() == exporttype::gre) { if (ret == 0) { this->_gre_count++; @@ -98,6 +143,10 @@ void PcapHandler::packetHandler(const struct pcap_pkthdr* header, const uint8_t* } _statislog->logSendStatis((uint64_t) (header->ts.tv_sec), header->caplen, _gre_count, _gre_drop_count, 0, _pcap_handle); + if (_need_update_status) { + AgentStatus::get_instance()->update_capture_status((uint64_t) (header->ts.tv_sec), header->caplen, + _gre_count, _gre_drop_count, _pcap_handle); + } } void PcapHandler::addExport(std::shared_ptr pcapExport) { @@ -130,6 +179,34 @@ void PcapHandler::stopPcapLoop() { pcap_breakloop(_pcap_handle); } +int PcapHandler::checkPktDirectionV4(const in_addr *sip, const in_addr *dip) { + for(auto& ipv4 : _ipv4s) + { + if(ipv4.s_addr == sip->s_addr) + return PKTD_OG; + else if(ipv4.s_addr == dip->s_addr) + return PKTD_IC; + } + return PKTD_UNKNOWN; +} + +int PcapHandler::checkPktDirectionV6(const in6_addr *sip, const in6_addr *dip) { + for(auto& ipv6 : _ipv6s) + { + if(ipv6.s6_addr32[0] == sip->s6_addr32[0] && + ipv6.s6_addr32[1] == sip->s6_addr32[1] && + ipv6.s6_addr32[2] == sip->s6_addr32[2] && + ipv6.s6_addr32[3] == sip->s6_addr32[3]) + return PKTD_OG; + else if(ipv6.s6_addr32[0] == dip->s6_addr32[0] && + ipv6.s6_addr32[1] == dip->s6_addr32[1] && + ipv6.s6_addr32[2] == dip->s6_addr32[2] && + ipv6.s6_addr32[3] == dip->s6_addr32[3]) + return PKTD_IC; + } + return PKTD_UNKNOWN; +} + int PcapOfflineHandler::openPcap(const std::string& dev, const pcap_init_t& param, const std::string& expression, bool dumpfile) { pcap_t* pcap_handle = pcap_open_offline(dev.c_str(), _errbuf); @@ -141,6 +218,7 @@ int PcapOfflineHandler::openPcap(const std::string& dev, const pcap_init_t& para auto pcapGuard = MakeGuard([pcap_handle]() { pcap_close(pcap_handle); }); + _need_update_status = param.need_update_status; if (dumpfile) { if (openPcapDumper(pcap_handle) != 0) { @@ -159,7 +237,31 @@ int PcapLiveHandler::openPcap(const std::string& dev, const pcap_init_t& param, struct bpf_program filter; bpf_u_int32 mask = 0; bpf_u_int32 net = 0; + _need_update_status = param.need_update_status; + + { + struct ifaddrs* ifaddr; + _ipv4s.clear(); + _ipv6s.clear(); + if (::getifaddrs(&ifaddr) < 0) { + return -1; + } + + for (auto ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if(!ifa->ifa_name || dev != ifa->ifa_name || !ifa->ifa_addr) + continue; + if(ifa->ifa_addr->sa_family == AF_INET) + { + _ipv4s.push_back(((sockaddr_in*)ifa->ifa_addr)->sin_addr); + } + else if(ifa->ifa_addr->sa_family == AF_INET6) + { + _ipv6s.push_back(((sockaddr_in6*)ifa->ifa_addr)->sin6_addr); + } + } + freeifaddrs(ifaddr); + } pcap_t* pcap_handle = pcap_create(dev.c_str(), _errbuf); if (!pcap_handle) { std::cerr << StatisLogContext::getTimeString() << "Call pcap_create failed, error is " << _errbuf << "." diff --git a/src/pcaphandler.h b/src/pcaphandler.h index 96f3479e0..e9e33a491 100644 --- a/src/pcaphandler.h +++ b/src/pcaphandler.h @@ -4,7 +4,12 @@ #include #include #include + #include + +#include + + #include "pcapexport.h" #include "statislog.h" @@ -13,6 +18,7 @@ typedef struct PcapInit { int timeout; int promisc; int buffer_size; + int need_update_status; } pcap_init_t; class PcapHandler { @@ -24,12 +30,23 @@ class PcapHandler { std::shared_ptr _statislog; uint64_t _gre_count; uint64_t _gre_drop_count; + std::string _dumpDir; std::int16_t _dumpInterval; std::time_t _timeStamp; + + int _need_update_status; + + std::vector _ipv4s; + std::vector _ipv6s; + + protected: int openPcapDumper(pcap_t *pcap_handle); void closePcapDumper(); + + int checkPktDirectionV4(const in_addr* sip, const in_addr* dip); + int checkPktDirectionV6(const in6_addr* sip, const in6_addr* dip); public: PcapHandler(std::string dumpDir, int16_t dumpInterval); virtual ~PcapHandler(); diff --git a/src/pktminerg.cpp b/src/pktminerg.cpp index 3b09386dc..0bdde78f9 100644 --- a/src/pktminerg.cpp +++ b/src/pktminerg.cpp @@ -4,8 +4,14 @@ #include #include "pcaphandler.h" #include "socketgre.h" +#include "socketvxlan.h" +#include "socketzmq.h" #include "versioninfo.h" #include "syshelp.h" +#ifndef WIN32 + #include "agent_control_plane.h" + +#endif std::shared_ptr handler = nullptr; @@ -27,7 +33,13 @@ int main(int argc, const char* argv[]) { "specify pcap file for offline mode, mostly for test") ("remoteip,r", boost::program_options::value()->value_name("IPs"), "set gre remote IPs, seperate by ',' Example: -r 8.8.4.4,8.8.8.8") - ("keybit,k", boost::program_options::value()->default_value(1)->value_name("BIT"), + ("zmq_port,z", boost::program_options::value()->default_value(0)->value_name("ZMQ_PORT"), + "set remote zeromq server port to receive packets reliably; ZMQ_PORT default value 0 means disable.") + ("zmq_hwm,m", boost::program_options::value()->default_value(4096)->value_name("ZMQ_HWM"), + "set zeromq queue high watermark; ZMQ_HWM default value 100.") + ("keybit,k", boost::program_options::value()->default_value(1)->value_name("KEYBIT"), + "set gre key bit; BIT defaults 1") + ("vni,n", boost::program_options::value()->value_name("VNI"), "set gre key bit; BIT defaults 1") ("snaplen,s", boost::program_options::value()->default_value(2048)->value_name("LENGTH"), "set snoop packet snaplen; LENGTH defaults 2048 and units byte") @@ -41,12 +53,16 @@ int main(int argc, const char* argv[]) { ("cpu", boost::program_options::value()->value_name("ID"), "set cpu affinity ID") ("expression", boost::program_options::value>()->value_name("FILTER"), R"(filter packets with FILTER; FILTER as same as tcpdump BPF expression syntax)") + ("dump", boost::program_options::value()->default_value("./")->value_name("DUMP"), "specify pcap dump file dump dir") ("interval", boost::program_options::value()->default_value(-1)->value_name("INTERVAL"), "specify the interval for dump file creation") + ("nofilter", - "force no filter; only use when you confirm that the snoop interface is different from the gre interface"); + "force no filter; In online mode, only use when GRE interface " + "is set via CLI, AND you confirm that the snoop interface is " + "different from the gre interface."); boost::program_options::positional_options_description position; position.add("expression", -1); @@ -91,6 +107,10 @@ int main(int argc, const char* argv[]) { } int pmtudisc = -1; + int update_status = 0; +#ifdef WIN32 + //TODO: support pmtudisc_option on WIN32 +#else if (vm.count("pmtudisc_option")) { const auto pmtudisc_option = vm["pmtudisc_option"].as(); if (pmtudisc_option == "do") { @@ -105,6 +125,15 @@ int main(int argc, const char* argv[]) { return 1; } } + std::shared_ptr agent_control_plane; + if (vm.count("control")) { + const auto daemon_zmq_port = vm["control"].as(); + agent_control_plane = std::make_shared(daemon_zmq_port); + agent_control_plane->init_msg_server(); + update_status = 1; + } +#endif // WIN32 + if (!vm.count("remoteip") && !vm.count("dump")) { std::cerr << StatisLogContext::getTimeString() @@ -119,6 +148,9 @@ int main(int argc, const char* argv[]) { boost::algorithm::split(remoteips, remoteip, boost::algorithm::is_any_of(",")); } + int zmq_port = vm["zmq_port"].as(); + int zmq_hwm = vm["zmq_hwm"].as(); + int keybit = vm["keybit"].as(); std::string filter = ""; @@ -132,6 +164,21 @@ int main(int argc, const char* argv[]) { bool nofilter = false; if (vm.count("nofilter")) { nofilter = true; + if (vm.count("interface")) { + if (bind_device == "") { + std::cerr << StatisLogContext::getTimeString() << "Can't enable --nofilter option " + << "because GRE bind devices(-B) is not set, GRE packet might be sent via packet captured interface(-i)" + << std::endl; + return 1; + } else if (bind_device == vm["interface"].as()) { + std::cerr << StatisLogContext::getTimeString() << "Can't enable --nofilter option " + << "because packet captured interface(-i) is equal to GRE bind devices(-B)" + << std::endl; + return 1; + } else { + // valid + } + } } if (nofilter) { @@ -159,6 +206,7 @@ int main(int argc, const char* argv[]) { param.snaplen = vm["snaplen"].as(); param.promisc = 0; param.timeout = vm["timeout"].as() * 1000; + param.need_update_status = update_status; int nCount = vm["count"].as(); if (nCount < 0) { nCount = 0; @@ -217,15 +265,36 @@ int main(int argc, const char* argv[]) { } }); - // export gre - std::shared_ptr greExport = std::make_shared(remoteips, keybit, bind_device, pmtudisc); - int err = greExport->initExport(); - if (err != 0) { - std::cerr << StatisLogContext::getTimeString() - << "greExport initExport failed." << std::endl; - return err; + std::shared_ptr exportPtr = nullptr; + if (zmq_port != 0) { + exportPtr = std::make_shared(remoteips, zmq_port, zmq_hwm, keybit, bind_device, param.buffer_size); + int err = exportPtr->initExport(); + if (err != 0) { + std::cerr << StatisLogContext::getTimeString() + << "zmqExport initExport failed." << std::endl; + return err; + } } - handler->addExport(greExport); + else if(vm.count("vni")){ + int vni = vm["vni"].as(); + exportPtr = std::make_shared(remoteips, vni, bind_device, pmtudisc); + int err = exportPtr->initExport(); + if (err != 0) { + std::cerr << StatisLogContext::getTimeString() << "vxlanExport initExport failed." << std::endl; + return err; + } + } + else{ + // export gre + exportPtr = std::make_shared(remoteips, keybit, bind_device, pmtudisc); + int err = exportPtr->initExport(); + if (err != 0) { + std::cerr << StatisLogContext::getTimeString() << "greExport initExport failed." << std::endl; + return err; + } + } + handler->addExport(exportPtr); + // begin pcap snoop @@ -234,6 +303,6 @@ int main(int argc, const char* argv[]) { std::cout << StatisLogContext::getTimeString() << "End pcap snoop." << std::endl; // end - greExport->closeExport(); + exportPtr->closeExport(); return 0; } diff --git a/src/socketgre.cpp b/src/socketgre.cpp index 6d3c83789..27342b11f 100644 --- a/src/socketgre.cpp +++ b/src/socketgre.cpp @@ -65,13 +65,16 @@ int PcapExportGre::initSockets(size_t index, uint32_t keybit) { #else if (setsockopt(socketfd, SOL_SOCKET, SO_BINDTODEVICE, _bind_device.c_str(), _bind_device.length()) < 0) { std::cerr << StatisLogContext::getTimeString() << "SO_BINDTODEVICE failed, error code is " << errno - << ", error is " << strerror(errno) << "." - << std::endl; + << ", error is " << strerror(errno) << "." + << std::endl; return -1; } #endif // WIN32 } +#ifdef WIN32 + //TODO: bind device on WIN32 +#else if (_pmtudisc >= 0) { if (setsockopt(socketfd, SOL_IP, IP_MTU_DISCOVER, &_pmtudisc, sizeof(_pmtudisc)) == -1) { std::cerr << StatisLogContext::getTimeString() << "IP_MTU_DISCOVER failed, error code is " << errno @@ -80,6 +83,10 @@ int PcapExportGre::initSockets(size_t index, uint32_t keybit) { return -1; } } +#endif // WIN32 + + + } return 0; } @@ -109,20 +116,29 @@ int PcapExportGre::closeExport() { return 0; } -int PcapExportGre::exportPacket(const struct pcap_pkthdr* header, const uint8_t* pkt_data) { +int PcapExportGre::exportPacket(const struct pcap_pkthdr* header, const uint8_t* pkt_data, int direct) { int ret = 0; + if(direct == PKTD_UNKNOWN) { + return -1; + } + for (size_t i = 0; i < _remoteips.size(); ++i) { - ret |= exportPacket(i, header, pkt_data); + ret |= exportPacket(i, header, pkt_data, direct); } return ret; } -int PcapExportGre::exportPacket(size_t index, const struct pcap_pkthdr* header, const uint8_t* pkt_data) { +int PcapExportGre::exportPacket(size_t index, const struct pcap_pkthdr* header, const uint8_t* pkt_data, int direct) { auto& grebuffer = _grebuffers[index]; int socketfd = _socketfds[index]; auto& remote_addr = _remote_addrs[index]; size_t length = (size_t) (header->caplen <= 65535 ? header->caplen : 65535); + + grehdr_t* hdr; + hdr = (grehdr_t*)&*grebuffer.begin(); + hdr->keybit = htonl(_keybit | (direct << 28)); + std::memcpy(reinterpret_cast(&(grebuffer[sizeof(grehdr_t)])), reinterpret_cast(pkt_data), length); ssize_t nSend = sendto(socketfd, &(grebuffer[0]), length + sizeof(grehdr_t), 0, (struct sockaddr*) &remote_addr, diff --git a/src/socketgre.h b/src/socketgre.h index 55248d1a9..c36bb327e 100644 --- a/src/socketgre.h +++ b/src/socketgre.h @@ -22,14 +22,14 @@ class PcapExportGre : public PcapExportBase { private: int initSockets(size_t index, uint32_t keybit); - int exportPacket(size_t index, const struct pcap_pkthdr *header, const uint8_t *pkt_data); + int exportPacket(size_t index, const struct pcap_pkthdr *header, const uint8_t *pkt_data, int direct); public: PcapExportGre(const std::vector& remoteips, uint32_t keybit, const std::string& bind_device, const int pmtudisc); ~PcapExportGre(); int initExport(); - int exportPacket(const struct pcap_pkthdr *header, const uint8_t *pkt_data); + int exportPacket(const struct pcap_pkthdr *header, const uint8_t *pkt_data, int direct); int closeExport(); }; diff --git a/src/socketvxlan.cpp b/src/socketvxlan.cpp new file mode 100644 index 000000000..1a7506d15 --- /dev/null +++ b/src/socketvxlan.cpp @@ -0,0 +1,168 @@ +#include "socketvxlan.h" + +#include +#include +#ifdef WIN32 + #include + #include + #include + typedef SSIZE_T ssize_t; + #define usleep Sleep +#else +#include +#include +#endif +#include +#include "statislog.h" + +#define VXLAN_PORT 4789 + +typedef struct { + uint32_t vx_flags; + uint32_t vx_vni; +}vxlan_hdr_t; + +const int INVALIDE_SOCKET_FD = -1; + +PcapExportVxlan::PcapExportVxlan(const std::vector& remoteips, uint32_t vni, const std::string& bind_device, + const int pmtudisc) : + _remoteips(remoteips), + _vni(vni), + _bind_device(bind_device), + _pmtudisc(pmtudisc), + _socketfds(remoteips.size()), + _remote_addrs(remoteips.size()), + _vxlanbuffers(remoteips.size()) { + _type = exporttype::vxlan; + for (size_t i = 0; i < remoteips.size(); ++i) { + _socketfds[i] = INVALIDE_SOCKET_FD; + _vxlanbuffers[i].resize(65535 + sizeof(vxlan_hdr_t), '\0'); + } +} + +PcapExportVxlan::~PcapExportVxlan() { + closeExport(); +} + +int PcapExportVxlan::initSockets(size_t index) { + auto& socketfd = _socketfds[index]; + + if (socketfd == INVALIDE_SOCKET_FD) { + + _remote_addrs[index].sin_family = AF_INET; + _remote_addrs[index].sin_port = htons(VXLAN_PORT); + _remote_addrs[index].sin_addr.s_addr = inet_addr(_remoteips[index].c_str()); + + if ((socketfd = socket(AF_INET, SOCK_DGRAM, 0)) == INVALIDE_SOCKET_FD) { + std::cerr << StatisLogContext::getTimeString() << "Create socket failed, error code is " << errno + << ", error is " << strerror(errno) << "." + << std::endl; + return -1; + } + + if (_bind_device.length() > 0) { +#ifdef WIN32 + //TODO: bind device on WIN32 +#else + if (setsockopt(socketfd, SOL_SOCKET, SO_BINDTODEVICE, _bind_device.c_str(), _bind_device.length()) < 0) { + std::cerr << StatisLogContext::getTimeString() << "SO_BINDTODEVICE failed, error code is " << errno + << ", error is " << strerror(errno) << "." + << std::endl; + return -1; + } +#endif // WIN32 + } + +#ifdef WIN32 + //TODO: bind device on WIN32 +#else + if (_pmtudisc >= 0) { + if (setsockopt(socketfd, SOL_IP, IP_MTU_DISCOVER, &_pmtudisc, sizeof(_pmtudisc)) == -1) { + std::cerr << StatisLogContext::getTimeString() << "IP_MTU_DISCOVER failed, error code is " << errno + << ", error is " << strerror(errno) << "." + << std::endl; + return -1; + } + } +#endif // WIN32 + + + + } + return 0; +} + +int PcapExportVxlan::initExport() { + for (size_t i = 0; i < _remoteips.size(); ++i) { + int ret = initSockets(i); + if (ret != 0) { + std::cerr << "Failed with index: " << i << std::endl; + return ret; + } + } + return 0; +} + +int PcapExportVxlan::closeExport() { + for (size_t i = 0; i < _remoteips.size(); ++i) { + if (_socketfds[i] != INVALIDE_SOCKET_FD) { +#ifdef WIN32 + shutdown(_socketfds[i], SD_BOTH); +#else + close(_socketfds[i]); +#endif // WIN32 + _socketfds[i] = INVALIDE_SOCKET_FD; + } + } + return 0; +} + +int PcapExportVxlan::exportPacket(const struct pcap_pkthdr* header, const uint8_t* pkt_data, int direct) { + int ret = 0; + if(direct == PKTD_UNKNOWN) { + return -1; + } + + for (size_t i = 0; i < _remoteips.size(); ++i) { + ret |= exportPacket(i, header, pkt_data, direct); + } + return ret; +} + +int PcapExportVxlan::exportPacket(size_t index, const struct pcap_pkthdr* header, const uint8_t* pkt_data, int direct) { + auto& vxlanbuffer = _vxlanbuffers[index]; + int socketfd = _socketfds[index]; + auto& remote_addr = _remote_addrs[index]; + + size_t length = (size_t) (header->caplen <= 65535 ? header->caplen : 65535); + + vxlan_hdr_t* hdr; + hdr = (vxlan_hdr_t*)&*vxlanbuffer.begin(); + hdr->vx_flags = htonl(0x08000000); + hdr->vx_vni = htonl(_vni | (direct << 28)); + + std::memcpy(reinterpret_cast(&(vxlanbuffer[sizeof(vxlan_hdr_t)])), + reinterpret_cast(pkt_data), length); + ssize_t nSend = sendto(socketfd, &(vxlanbuffer[0]), length + sizeof(vxlan_hdr_t), 0, (struct sockaddr*) &remote_addr, + sizeof(struct sockaddr)); + while (nSend == -1 && errno == ENOBUFS) { + usleep(1000); + nSend = static_cast(sendto(socketfd, &(vxlanbuffer[0]), length + sizeof(vxlan_hdr_t), 0, + (struct sockaddr*) &remote_addr, + sizeof(struct sockaddr))); + } + if (nSend == -1) { + std::cerr << StatisLogContext::getTimeString() << "Send to socket failed, error code is " << errno + << ", error is " << strerror(errno) << "." + << std::endl; + return -1; + } + if (nSend < (ssize_t) (length + sizeof(vxlan_hdr_t))) { + std::cerr << StatisLogContext::getTimeString() << "Send socket " << length + sizeof(vxlan_hdr_t) + << " bytes, but only " << nSend << + " bytes are sent success." << std::endl; + return 1; + } + return 0; +} + diff --git a/src/socketvxlan.h b/src/socketvxlan.h new file mode 100644 index 000000000..1a56cfbfd --- /dev/null +++ b/src/socketvxlan.h @@ -0,0 +1,35 @@ +#ifndef SRC_SOCKETVXLAN_H_ +#define SRC_SOCKETVXLAN_H_ + +#ifndef WIN32 + #include +#endif +#include +#include +#include "pcapexport.h" + + +class PcapExportVxlan : public PcapExportBase { +protected: + std::vector _remoteips; + uint32_t _vni; + std::string _bind_device; + int _pmtudisc; + std::vector _socketfds; + std::vector _remote_addrs; + std::vector> _vxlanbuffers; + +private: + int initSockets(size_t index); + int exportPacket(size_t index, const struct pcap_pkthdr *header, const uint8_t *pkt_data, int direct); + +public: + PcapExportVxlan(const std::vector& remoteips, uint32_t vni, const std::string& bind_device, + const int pmtudisc); + ~PcapExportVxlan(); + int initExport(); + int exportPacket(const struct pcap_pkthdr *header, const uint8_t *pkt_data, int direct); + int closeExport(); +}; + +#endif // SRC_SOCKETVXLAN_H_ diff --git a/src/socketzmq.cpp b/src/socketzmq.cpp new file mode 100644 index 000000000..41002da67 --- /dev/null +++ b/src/socketzmq.cpp @@ -0,0 +1,142 @@ +#include "socketzmq.h" + +#include +#include +#ifdef WIN32 + #include + #include + #include + typedef SSIZE_T ssize_t; + #define usleep Sleep + #define IPPROTO_GRE 47 +#else +#include +#include +#endif +#include +#include "statislog.h" + + +PcapExportZMQ::PcapExportZMQ(const std::vector& remoteips, int zmq_port, int zmq_hwm, uint32_t keybit, + const std::string& bind_device, const int send_buf_size) : + _remoteips(remoteips), + _zmq_port(zmq_port), + _zmq_hwm(zmq_hwm), + _keybit(keybit), + _bind_device(bind_device), + _send_buf_size(send_buf_size), + _pkts_bufs(remoteips.size()) { + _type = exporttype::zmq; + for (size_t i = 0; i < remoteips.size(); ++i) { + _pkts_bufs[i].buf.resize(MAX_BATCH_BUF_LENGTH, '\0'); + _pkts_bufs[i].batch_bufpos = sizeof(batch_pkts_hdr_t); + _pkts_bufs[i].batch_hdr = { htons(BatchPktsBuf::BATCH_PKTS_VERSION), 0, htonl(keybit) }; + _pkts_bufs[i].first_pktsec = 0; + } +} + +PcapExportZMQ::~PcapExportZMQ() { + closeExport(); +} + +int PcapExportZMQ::initSockets(size_t index, uint32_t keybit) { + (void)keybit; + + _zmq_contexts.emplace_back(1); + _zmq_sockets.emplace_back(_zmq_contexts[index], ZMQ_PUSH); + zmq::socket_t& socket = _zmq_sockets[index]; + std::string connect_addr = "tcp://" + _remoteips[index] + ":" + std::to_string(_zmq_port); + + int32_t linger_ms = 10 * 1000; + for (size_t i = 0; i < _remoteips.size(); ++i) { + _zmq_sockets[i].set(zmq::sockopt::linger, linger_ms); + _zmq_sockets[i].set(zmq::sockopt::sndhwm, _zmq_hwm); + } + + socket.connect(connect_addr); + return 0; +} + +int PcapExportZMQ::initExport() { + for (size_t i = 0; i < _remoteips.size(); ++i) { + int ret = initSockets(i, _keybit); + if (ret != 0) { + std::cerr << "Failed with index: " << i << std::endl; + return ret; + } + } + return 0; +} + +int PcapExportZMQ::closeExport() { + for (size_t i = 0; i < _zmq_sockets.size(); ++i) { + flushBatchBuf(i); + } + _zmq_sockets.clear(); + _zmq_contexts.clear(); + return 0; +} + + +int PcapExportZMQ::exportPacket(const struct pcap_pkthdr* header, const uint8_t* pkt_data, int direct) { + int ret = 0; + for (size_t i = 0; i < _remoteips.size(); ++i) { + ret += exportPacket(i, header, pkt_data, direct); + } + return ret; +} + + +int PcapExportZMQ::flushBatchBuf(size_t index) { + auto& pkts_buf = _pkts_bufs[index]; + auto& socket = _zmq_sockets[index]; + auto& buf = pkts_buf.buf; + + int drop_pkts_num = pkts_buf.batch_hdr.pkts_num; + pkts_buf.batch_hdr.pkts_num = htons(pkts_buf.batch_hdr.pkts_num); + std::memcpy(reinterpret_cast(&(buf[0])), &pkts_buf.batch_hdr, sizeof(pkts_buf.batch_hdr)); + + auto ret = socket.send(zmq::buffer(&buf[0], pkts_buf.batch_bufpos), zmq::send_flags::dontwait); + if (ret.has_value()) { + drop_pkts_num = 0; + } else { + // std::cout<<"send failed."<ts.tv_sec; + } + + uint16_t length = (uint16_t) (header->caplen <= 65535 ? header->caplen : 65535); + + pmr_pkthdr_t small_pkthdr = { htonl((uint32_t)header->ts.tv_sec), + htonl((uint32_t)header->ts.tv_usec), + htonl((uint32_t)header->caplen), + htonl((uint32_t)header->len) }; + auto& buf = pkts_buf.buf; + if (pkts_buf.batch_hdr.pkts_num >= 65535 + || header->ts.tv_sec > pkts_buf.first_pktsec + MAX_PKTS_TIMEDIFF_S // 3 second timeout + || pkts_buf.batch_bufpos + sizeof(length) + sizeof(small_pkthdr) + length > MAX_BATCH_BUF_LENGTH) { + + drop_pkts_num = flushBatchBuf(index); + + pkts_buf.first_pktsec = header->ts.tv_sec; + pkts_buf.batch_bufpos = sizeof(pkts_buf.batch_hdr); + pkts_buf.batch_hdr.pkts_num = 0; + } + + uint16_t hlen = htons(length); + std::memcpy(&(buf[pkts_buf.batch_bufpos]), &hlen, sizeof(hlen)); + std::memcpy(&(buf[pkts_buf.batch_bufpos + sizeof(length)]), &small_pkthdr, sizeof(small_pkthdr)); + std::memcpy(&(buf[pkts_buf.batch_bufpos + sizeof(length) + sizeof(small_pkthdr)]), pkt_data, length); + pkts_buf.batch_bufpos += sizeof(length) + sizeof(small_pkthdr) + length; + pkts_buf.batch_hdr.pkts_num++; + return drop_pkts_num; +} diff --git a/src/socketzmq.h b/src/socketzmq.h new file mode 100644 index 000000000..96a2f1e35 --- /dev/null +++ b/src/socketzmq.h @@ -0,0 +1,67 @@ +#ifndef SRC_SOCKETZMQ_H_ +#define SRC_SOCKETZMQ_H_ + +#ifndef WIN32 + #include +#endif +#include +#include +#include "zmq.hpp" +#include "pcapexport.h" + + + +typedef struct PmrPktHdr { + uint32_t tv_sec; // epoc seconds. caution: unix 2038 problem + uint32_t tv_usec; // and microseconds + uint32_t caplen; // actual capture length + uint32_t len; // wire packet length +} pmr_pkthdr_t, * pmr_pkthdr_ptr_t; + +typedef struct batch_pkts_header { + uint16_t version; + uint16_t pkts_num; + uint32_t keybit; +} batch_pkts_hdr_t; + +struct BatchPktsBuf { + batch_pkts_hdr_t batch_hdr; + // buf format as below: + // | batch_hdr | (pkt_data length + pkt_hdr + pkt_data) | (pkt_data_length + pkt_hdr + pkt_data) | ... + // | 8 bytes | (2 bytes + 16 bytes + n bytes ) | (2 bytes + 16 bytes + n bytes ) | ... + std::vector buf; + uint32_t batch_bufpos; + __time_t first_pktsec; +public: + static constexpr uint16_t BATCH_PKTS_VERSION = 1; +}; + +class PcapExportZMQ : public PcapExportBase { +protected: + std::vector _remoteips; + int _zmq_port; + int _zmq_hwm; + uint32_t _keybit; + std::string _bind_device; + int _send_buf_size; + std::vector _zmq_contexts; + std::vector _zmq_sockets; + std::vector _pkts_bufs; + constexpr static uint32_t MAX_PKTS_TIMEDIFF_S = 1; + constexpr static uint32_t MAX_BATCH_BUF_LENGTH = 1 * 1024 * 1024; + +private: + int initSockets(size_t index, uint32_t keybit); + int exportPacket(size_t index, const struct pcap_pkthdr *header, const uint8_t *pkt_data, int direct); + int flushBatchBuf(size_t index); + +public: + PcapExportZMQ(const std::vector& remoteips, int zmq_port, int zmq_hwm, uint32_t keybit, + const std::string& bind_device, const int send_buf_size); + ~PcapExportZMQ(); + int initExport(); + int exportPacket(const struct pcap_pkthdr *header, const uint8_t *pkt_data, int direct); + int closeExport(); +}; + +#endif // SRC_SOCKETZMQ_H_ \ No newline at end of file diff --git a/src/vlan.h b/src/vlan.h new file mode 100644 index 000000000..41aa8c786 --- /dev/null +++ b/src/vlan.h @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap/vlan.h,v 1.1 2008-08-06 07:45:00 guy Exp $ + */ + +#ifndef lib_pcap_vlan_h +#define lib_pcap_vlan_h + +struct vlan_tag { + u_int16_t vlan_tpid; /* ETH_P_8021Q */ + u_int16_t vlan_tci; /* VLAN TCI */ +}; + +#define VLAN_TAG_LEN 4 + +#endif diff --git a/test/test_control_plane.sh b/test/test_control_plane.sh new file mode 100644 index 000000000..e6bd12b5a --- /dev/null +++ b/test/test_control_plane.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +NIC=$1 +if [ ! $1 ]; then + NIC='eth0' +fi + +../bin/pktminerg -i $NIC -r 172.16.14.249 --control 5556 & +sleep 10 +python test_control_plane_client.py +sleep 10 +killall pktminerg + diff --git a/test/test_control_plane_client.py b/test/test_control_plane_client.py new file mode 100644 index 000000000..0835650ff --- /dev/null +++ b/test/test_control_plane_client.py @@ -0,0 +1,41 @@ +#!/bin/env python +# -*- coding: utf-8 -*- + + +import zmq +import time +from struct import pack, unpack, calcsize +from docopt import docopt +from IPy import IP + + + + +PKT_SERVER = 'tcp://127.0.0.1:5556' +TIME_OUT = 5000 + +DIAG_TYPE_SLICE = 0 +DIAG_TYPE_FILTER = 1 +#DIAG_TYPE_DEEP_SLICE = 2 +DIAG_TYPE_BTR = 3 + +# msg_item = self.msg_map["%s_%s" % (self._opt, self._msg_operand)] +message = pack('=iiii', 0x504D3230, 0x10, + 0x0001, + 0x0f0f) +socket = zmq.Context().socket(zmq.REQ) +socket.setsockopt(zmq.LINGER, 0) +poll_obj = zmq.Poller() +poll_obj.register(socket, zmq.POLLIN) +socket.connect(PKT_SERVER) +socket.send(message) +event = dict(poll_obj.poll(TIME_OUT)) +ret = (0x504D3230, 0x0C, 0xFFFF, 0x0) +if event.get(socket) == zmq.POLLIN : + response = socket.recv() + ret = unpack('=iiiiiiiiiiii', + response[0: 48]) + +print ret +socket.close() + diff --git a/test/test_recvzmq.sh b/test/test_recvzmq.sh new file mode 100755 index 000000000..29f3cae39 --- /dev/null +++ b/test/test_recvzmq.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +rm -rf ./nic1/* + +python ../scripts/recvzmq/recvzmq.py -z 5555 -t ./nic1/%Y%m%d%H%M%S -s 15 -a 1 & +../bin/pktminerg -f xml.pcap -r 127.0.0.1 -k 15 -z 5555 & +sleep 20 + +tshark -r ./nic1/20130327104800_1_0.pcap | grep -v :00_00: > ./nic1/xmltshark.txt +sed -i 's/^ *[0-9]\+ *[0-9.]\+ //g' ./nic1/xmltshark.txt + +killall pktminerg +ps -ef | grep python.*recvzmq.py | grep -v grep | awk '{print $2}' | xargs kill + +diff xmltshark_baseline.txt ./nic1/xmltshark.txt +if [ $? -eq 0 ]; then + echo "test 1 ok" +else + echo "test 1 failed" + exit 1 +fi + + + + +rm -rf ./nic2/* +python ../scripts/recvzmq/recvzmq.py -z 5555 -t ./nic2/%Y%m%d%H%M%S -s 15 -a 2 & +../bin/pktminerg -f xml.pcap -r 127.0.0.1 -k 3 -z 5555 & +sleep 20 + +mergecap -w mergedgre.pcap ./nic2/*.pcap +mv mergedgre.pcap ./nic2/ +tshark -r ./nic2/mergedgre.pcap | grep -v :00_00: > ./nic2/xmltshark2.txt +sed -i 's/^ *[0-9]\+ *[0-9.]\+ //g' ./nic2/xmltshark2.txt + +killall pktminerg +ps -ef | grep python.*recvzmq.py | grep -v grep | awk '{print $2}' | xargs kill + +diff xmltshark_baseline.txt ./nic2/xmltshark2.txt +if [ $? -eq 0 ]; then + echo "test 2 ok" +else + echo "test 2 failed" + exit 1 +fi + diff --git a/test/unit_test.cpp b/test/unit_test.cpp index 4b3b21ce6..9a65d744f 100644 --- a/test/unit_test.cpp +++ b/test/unit_test.cpp @@ -2,6 +2,8 @@ #include "../src/syshelp.h" #include "../src/pcaphandler.h" #include "../src/socketgre.h" +#include "../src/agent_status.h" +#include "../src/agent_control_plane.h" namespace { TEST(SysHelpTest, test) { @@ -14,7 +16,7 @@ namespace { return 0; } - int exportPacket(const struct pcap_pkthdr* header, const uint8_t* pkt_data) { + int exportPacket(const struct pcap_pkthdr* header, const uint8_t* pkt_data, int direct) { return 0; } @@ -40,8 +42,29 @@ namespace { header.caplen = 32; header.len = 32; std::vector pkt_data(32); - EXPECT_EQ(0, greExport.exportPacket(&header, pkt_data.data())); + EXPECT_EQ(0, greExport.exportPacket(&header, pkt_data.data(), PKTD_NONCHECK)); EXPECT_EQ(0, greExport.closeExport()); } + TEST(AgentStatusQuery, test) { + // AgentStatus::get_instance()->update_status(1586508861, header->caplen, + // _gre_count, _gre_drop_count, _pcap_handle); + AgentStatus* inst = AgentStatus::get_instance(); + inst->reset_agent_status(); + inst->update_capture_status(1586508861, 200, 1, 0, nullptr); + inst->update_capture_status(1586508862, 200, 1, 0, nullptr); + inst->update_capture_status(1586508863, 100, 1, 0, nullptr); + EXPECT_EQ(1586508861, static_cast(inst->first_packet_time())); + EXPECT_EQ(1586508863, static_cast(inst->last_packet_time())); + EXPECT_EQ(500, static_cast(inst->total_cap_bytes())); + } + + TEST(AgentControlPlane, test) { + + AgentControlPlane zmq_server(5556); + EXPECT_EQ(0, zmq_server.init_msg_server()); + sleep(1); + zmq_server.close_msg_server(); + } + } \ No newline at end of file diff --git a/test/xmltshark_baseline.txt b/test/xmltshark_baseline.txt new file mode 100644 index 000000000..8f2b84a61 --- /dev/null +++ b/test/xmltshark_baseline.txt @@ -0,0 +1,1200 @@ +172.16.11.181 -> 172.16.101.164 SSH 228 Encrypted response packet len=132 +172.16.101.164 -> 172.16.11.181 TCP 102 64028 > ssh [ACK] Seq=1 Ack=133 Win=63016 Len=0 +Cisco_eb:82:1a -> CDP/VTP/DTP/PAgP/UDLD VTP 230 Join +Cisco_e9:c6:9a -> CDP/VTP/DTP/PAgP/UDLD VTP 230 Join +Cisco_df:87:00 -> Broadcast ARP 102 Who has 172.16.11.162? Tell 172.16.11.1 +Vmware_ab:6d:9d -> Broadcast ARP 102 Who has 172.16.24.71? Tell 172.16.24.8 +Cisco_05:6f:9a -> CDP/VTP/DTP/PAgP/UDLD VTP 230 Join +172.16.101.164 -> 172.16.11.181 SSH 148 Encrypted request packet len=52 +172.16.11.181 -> 172.16.101.164 TCP 96 ssh > 64028 [ACK] Seq=133 Ack=53 Win=63784 Len=0 +172.16.101.164 -> 172.16.11.181 SSH 148 Encrypted request packet len=52 +172.16.11.181 -> 172.16.101.164 TCP 96 ssh > 64028 [ACK] Seq=133 Ack=105 Win=63784 Len=0 +172.16.11.181 -> 172.16.101.164 SSH 404 Encrypted response packet len=308 +172.16.11.181 -> 172.16.101.164 SSH 404 Encrypted response packet len=308 +172.16.11.181 -> 172.16.101.164 SSH 404 Encrypted response packet len=308 +172.16.101.164 -> 172.16.11.181 TCP 102 64028 > ssh [ACK] Seq=105 Ack=1057 Win=64240 Len=0 +172.16.11.181 -> 172.16.101.164 SSH 1556 Encrypted response packet len=1460 +172.16.11.181 -> 172.16.101.164 SSH 260 Encrypted response packet len=164 +172.16.101.164 -> 172.16.11.181 TCP 102 64028 > ssh [ACK] Seq=105 Ack=2681 Win=64240 Len=0 +Cisco_df:87:00 -> Broadcast ARP 102 Who has 172.16.11.115? Tell 172.16.11.1 +172.16.101.164 -> 172.16.11.181 SSH 148 Encrypted request packet len=52 +172.16.11.181 -> 172.16.101.164 SSH 148 Encrypted response packet len=52 +172.16.11.181 -> 172.16.101.164 SSH 228 Encrypted response packet len=132 +172.16.11.181 -> 172.16.11.180 TCP 116 50315 > 23180 [SYN] Seq=0 Win=5840 Len=0 MSS=1460 SACK_PERM=1 TSval=495202725 TSecr=0 WS=128 +172.16.11.181 -> 172.16.101.164 SSH 180 Encrypted response packet len=84 +172.16.11.180 -> 172.16.11.181 TCP 116 23180 > 50315 [SYN, ACK] Seq=0 Ack=1 Win=14480 Len=0 MSS=1460 SACK_PERM=1 TSval=3197407014 TSecr=495202725 WS=128 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=1 Ack=1 Win=5888 Len=0 TSval=495202726 TSecr=3197407014 +172.16.11.181 -> 172.16.11.180 TCP 258 50315 > 23180 [PSH, ACK] Seq=1 Ack=1 Win=5888 Len=150 TSval=495202726 TSecr=3197407014 +172.16.101.164 -> 172.16.11.181 TCP 102 64028 > ssh [ACK] Seq=157 Ack=2865 Win=64056 Len=0 +172.16.11.181 -> 172.16.101.164 SSH 148 Encrypted response packet len=52 +172.16.11.181 -> 172.16.101.164 SSH 180 Encrypted response packet len=84 +172.16.11.180 -> 172.16.11.181 TCP 108 23180 > 50315 [ACK] Seq=1 Ack=151 Win=15616 Len=0 TSval=3197407014 TSecr=495202726 +172.16.101.164 -> 172.16.11.181 TCP 102 64028 > ssh [ACK] Seq=157 Ack=3085 Win=63836 Len=0 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1449 Win=8832 Len=0 TSval=495202726 TSecr=3197407014 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=2897 Win=11648 Len=0 TSval=495202726 TSecr=3197407014 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=4345 Win=14592 Len=0 TSval=495202726 TSecr=3197407014 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=5793 Win=17536 Len=0 TSval=495202726 TSecr=3197407014 +172.16.11.181 -> 172.16.101.164 SSH 164 Encrypted response packet len=68 +172.16.11.181 -> 172.16.101.164 SSH 164 Encrypted response packet len=68 +172.16.11.181 -> 172.16.101.164 SSH 180 Encrypted response packet len=84 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=7241 Win=20352 Len=0 TSval=495202726 TSecr=3197407014 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=8689 Win=23296 Len=0 TSval=495202726 TSecr=3197407014 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=10137 Win=26112 Len=0 TSval=495202726 TSecr=3197407014 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=11585 Win=29056 Len=0 TSval=495202726 TSecr=3197407014 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=13033 Win=32000 Len=0 TSval=495202726 TSecr=3197407014 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=14481 Win=34816 Len=0 TSval=495202726 TSecr=3197407014 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=15929 Win=37760 Len=0 TSval=495202727 TSecr=3197407014 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=17377 Win=40704 Len=0 TSval=495202727 TSecr=3197407014 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.101.164 -> 172.16.11.181 TCP 102 64028 > ssh [ACK] Seq=157 Ack=3221 Win=63700 Len=0 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=18825 Win=43520 Len=0 TSval=495202727 TSecr=3197407014 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=20273 Win=46464 Len=0 TSval=495202727 TSecr=3197407014 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=21721 Win=49280 Len=0 TSval=495202727 TSecr=3197407014 +172.16.11.181 -> 172.16.101.164 SSH 148 Encrypted response packet len=52 +172.16.11.181 -> 172.16.101.164 SSH 308 Encrypted response packet len=212 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=23169 Win=52224 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=24617 Win=55168 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=26065 Win=57984 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=27513 Win=60928 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=28961 Win=61312 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=30409 Win=59904 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=31857 Win=58368 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=41993 Win=63872 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.101.164 -> 172.16.11.181 TCP 102 64028 > ssh [ACK] Seq=157 Ack=3357 Win=63564 Len=0 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=49233 Win=63872 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=50681 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=53577 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=56473 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=59369 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=62265 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=65161 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=68057 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=70953 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=73849 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=76745 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=79641 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=82537 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=88329 Win=59904 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=91225 Win=62720 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=94121 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=97017 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=99913 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=102809 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=105705 Win=64128 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=108601 Win=61312 Len=0 TSval=495202727 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=114393 Win=64128 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=115841 Win=67072 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=117289 Win=69888 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=118737 Win=72832 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=120185 Win=75776 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=121633 Win=78592 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=123081 Win=81536 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=124529 Win=84480 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=125977 Win=87296 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=127425 Win=90240 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=128873 Win=93056 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=130321 Win=96000 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=131769 Win=98944 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=133217 Win=101760 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=134665 Win=104704 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=136113 Win=107648 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=137561 Win=110464 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=139009 Win=113408 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=140457 Win=116224 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=141905 Win=119168 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=143353 Win=122112 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=144801 Win=124928 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=146249 Win=127872 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=147697 Win=130816 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=149145 Win=133632 Len=0 TSval=495202728 TSecr=3197407015 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=150593 Win=136576 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=152041 Win=139392 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=153489 Win=142336 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=154937 Win=145280 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=156385 Win=148096 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=157833 Win=151040 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=159281 Win=153984 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=160729 Win=156800 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=162177 Win=159744 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=163625 Win=162560 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=165073 Win=165504 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=166521 Win=168448 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=167969 Win=171264 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=169417 Win=174208 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=170865 Win=177152 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=172313 Win=179968 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=173761 Win=182912 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=175209 Win=185728 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=176657 Win=188288 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=179553 Win=188288 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=185345 Win=184576 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=191137 Win=188288 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=194033 Win=188288 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=196929 Win=188288 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=199825 Win=188288 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=202721 Win=188288 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=205617 Win=188288 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=212857 Win=183040 Len=0 TSval=495202728 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=360553 Win=36864 Len=0 TSval=495202768 TSecr=3197407016 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=396753 Win=640 Len=0 TSval=495202808 TSecr=3197407056 +Dell_75:2c:0e -> Broadcast ARP 102 Gratuitous ARP for 192.168.0.120 (Reply) +172.16.101.164 -> 172.16.11.181 TCP 102 64028 > ssh [ACK] Seq=157 Ack=3569 Win=63352 Len=0 +172.16.11.181 -> 172.16.11.180 TCP 108 [TCP Window Update] 50315 > 23180 [ACK] Seq=151 Ack=396753 Win=25472 Len=0 TSval=495202931 TSecr=3197407056 +172.16.11.181 -> 172.16.11.180 TCP 108 [TCP Window Update] 50315 > 23180 [ACK] Seq=151 Ack=396753 Win=58496 Len=0 TSval=495202931 TSecr=3197407056 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=399649 Win=87168 Len=0 TSval=495202931 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=418473 Win=85632 Len=0 TSval=495202931 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=421369 Win=98560 Len=0 TSval=495202931 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=428609 Win=107136 Len=0 TSval=495202931 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=441641 Win=111488 Len=0 TSval=495202931 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=456121 Win=188288 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=457569 Win=191232 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=459017 Win=194048 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=460465 Win=196992 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=461913 Win=199936 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=463361 Win=202752 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=464809 Win=205696 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=466257 Win=208512 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=467705 Win=211456 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=469153 Win=214400 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=470601 Win=217216 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=472049 Win=220160 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=473497 Win=223104 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=474945 Win=225920 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.181 -> 172.16.101.164 SSH 308 Encrypted response packet len=212 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=482185 Win=225920 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=483633 Win=228864 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=485081 Win=231680 Len=0 TSval=495202932 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +Cisco_eb:82:19 -> CDP/VTP/DTP/PAgP/UDLD CDP 468 Device ID: SW1.netis.com.cn Port ID: GigabitEthernet0/1 +Cisco_eb:82:1a -> CDP/VTP/DTP/PAgP/UDLD CDP 468 Device ID: SW1.netis.com.cn Port ID: GigabitEthernet0/2 +Cisco_eb:82:1a -> CDP/VTP/DTP/PAgP/UDLD DTP 102 Dynamic Trunking Protocol +Cisco_eb:82:19 -> CDP/VTP/DTP/PAgP/UDLD DTP 102 Dynamic Trunking Protocol +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=634225 Win=84096 Len=0 TSval=495202972 TSecr=3197407219 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=699385 Win=19456 Len=0 TSval=495203012 TSecr=3197407260 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=718209 Win=512 Len=0 TSval=495203052 TSecr=3197407300 +Cisco_df:87:1a -> PVST+ STP 106 Conf. Root = 24576/1/00:0f:f7:df:87:00 Cost = 0 Port = 0x8041 +Cisco_df:87:1a -> Spanning-tree-(for-bridges)_00 STP 102 Conf. Root = 24576/1/00:0f:f7:df:87:00 Cost = 0 Port = 0x8041 +172.16.101.164 -> 172.16.11.181 TCP 102 64028 > ssh [ACK] Seq=157 Ack=3781 Win=63140 Len=0 +172.16.11.181 -> 172.16.11.180 TCP 108 [TCP Window Update] 50315 > 23180 [ACK] Seq=151 Ack=718209 Win=16640 Len=0 TSval=495203138 TSecr=3197407300 +172.16.11.181 -> 172.16.101.164 SSH 308 Encrypted response packet len=212 +172.16.11.181 -> 172.16.11.180 TCP 108 [TCP Window Update] 50315 > 23180 [ACK] Seq=151 Ack=718209 Win=33792 Len=0 TSval=495203138 TSecr=3197407300 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=721105 Win=46720 Len=0 TSval=495203138 TSecr=3197407426 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=724001 Win=59648 Len=0 TSval=495203138 TSecr=3197407426 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=731241 Win=68224 Len=0 TSval=495203138 TSecr=3197407426 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=745721 Win=71168 Len=0 TSval=495203138 TSecr=3197407426 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=748617 Win=84096 Len=0 TSval=495203139 TSecr=3197407426 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=751513 Win=96896 Len=0 TSval=495203139 TSecr=3197407426 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=767441 Win=98432 Len=0 TSval=495203139 TSecr=3197407426 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=770337 Win=111232 Len=0 TSval=495203139 TSecr=3197407427 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=779025 Win=118400 Len=0 TSval=495203139 TSecr=3197407427 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=789161 Win=125568 Len=0 TSval=495203139 TSecr=3197407427 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=803641 Win=127104 Len=0 TSval=495203139 TSecr=3197407427 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=894865 Win=36736 Len=0 TSval=495203179 TSecr=3197407427 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=931065 Win=512 Len=0 TSval=495203219 TSecr=3197407467 +172.16.101.164 -> 172.16.11.181 TCP 102 64028 > ssh [ACK] Seq=157 Ack=3993 Win=62928 Len=0 +172.16.11.181 -> 172.16.11.180 TCP 108 [TCP Window Update] 50315 > 23180 [ACK] Seq=151 Ack=931065 Win=16640 Len=0 TSval=495203346 TSecr=3197407467 +172.16.11.181 -> 172.16.101.164 SSH 308 Encrypted response packet len=212 +172.16.11.181 -> 172.16.11.180 TCP 108 [TCP Window Update] 50315 > 23180 [ACK] Seq=151 Ack=931065 Win=33792 Len=0 TSval=495203346 TSecr=3197407467 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=933961 Win=46720 Len=0 TSval=495203346 TSecr=3197407634 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=936857 Win=59648 Len=0 TSval=495203346 TSecr=3197407634 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=948441 Win=65408 Len=0 TSval=495203346 TSecr=3197407634 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=960025 Win=69760 Len=0 TSval=495203346 TSecr=3197407634 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=962921 Win=82560 Len=0 TSval=495203347 TSecr=3197407634 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=965817 Win=96896 Len=0 TSval=495203347 TSecr=3197407634 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=983193 Win=95488 Len=0 TSval=495203347 TSecr=3197407634 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=986089 Win=108416 Len=0 TSval=495203347 TSecr=3197407635 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1003465 Win=107008 Len=0 TSval=495203347 TSecr=3197407635 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1013601 Win=114176 Len=0 TSval=495203347 TSecr=3197407635 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1016497 Win=127104 Len=0 TSval=495203347 TSecr=3197407635 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1142473 Win=2304 Len=0 TSval=495203387 TSecr=3197407635 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1143921 Win=768 Len=0 TSval=495203427 TSecr=3197407675 +172.16.101.164 -> 172.16.11.181 TCP 102 64028 > ssh [ACK] Seq=157 Ack=4205 Win=64240 Len=0 +172.16.11.181 -> 172.16.11.180 TCP 108 [TCP Window Update] 50315 > 23180 [ACK] Seq=151 Ack=1143921 Win=16640 Len=0 TSval=495203554 TSecr=3197407675 +172.16.11.181 -> 172.16.101.164 SSH 308 Encrypted response packet len=212 +172.16.11.181 -> 172.16.11.180 TCP 108 [TCP Window Update] 50315 > 23180 [ACK] Seq=151 Ack=1143921 Win=33792 Len=0 TSval=495203554 TSecr=3197407675 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1146817 Win=46720 Len=0 TSval=495203554 TSecr=3197407842 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1149713 Win=59648 Len=0 TSval=495203554 TSecr=3197407842 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1161297 Win=65408 Len=0 TSval=495203554 TSecr=3197407842 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1172881 Win=69760 Len=0 TSval=495203554 TSecr=3197407842 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1175777 Win=82560 Len=0 TSval=495203555 TSecr=3197407842 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1185913 Win=89728 Len=0 TSval=495203555 TSecr=3197407842 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1191705 Win=99840 Len=0 TSval=495203555 TSecr=3197407842 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1204737 Win=102656 Len=0 TSval=495203555 TSecr=3197407842 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1209081 Win=115584 Len=0 TSval=495203555 TSecr=3197407843 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1223561 Win=116992 Len=0 TSval=495203555 TSecr=3197407843 +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1227905 Win=128512 Len=0 TSval=495203555 TSecr=3197407843 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1350985 Win=6656 Len=0 TSval=495203595 TSecr=3197407843 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1356777 Win=768 Len=0 TSval=495203635 TSecr=3197407883 +Cisco_df:87:1a -> CDP/VTP/DTP/PAgP/UDLD VTP 230 Join +Cisco_df:87:00 -> Broadcast ARP 102 Who has 172.16.24.1? Tell 172.16.24.254 +172.16.101.164 -> 172.16.11.181 TCP 102 64028 > ssh [ACK] Seq=157 Ack=4417 Win=64028 Len=0 +172.16.11.181 -> 172.16.11.180 TCP 108 [TCP Window Update] 50315 > 23180 [ACK] Seq=151 Ack=1356777 Win=18048 Len=0 TSval=495203762 TSecr=3197407883 +172.16.11.181 -> 172.16.101.164 SSH 308 Encrypted response packet len=212 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 [TCP Window Update] 50315 > 23180 [ACK] Seq=151 Ack=1356777 Win=49664 Len=0 TSval=495203762 TSecr=3197407883 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1359673 Win=62592 Len=0 TSval=495203762 TSecr=3197408050 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1362569 Win=76928 Len=0 TSval=495203762 TSecr=3197408050 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1379945 Win=75392 Len=0 TSval=495203762 TSecr=3197408050 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.181 -> 172.16.11.180 TCP 108 50315 > 23180 [ACK] Seq=151 Ack=1382841 Win=88320 Len=0 TSval=495203763 TSecr=3197408050 +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] +172.16.11.180 -> 172.16.11.181 TCP 1556 [TCP segment of a reassembled PDU] diff --git a/tools/gredemo.cpp b/tools/gredemo.cpp index 5896ba02a..766eddc1c 100644 --- a/tools/gredemo.cpp +++ b/tools/gredemo.cpp @@ -114,10 +114,9 @@ int main(int argc, const char* argv[]) { // read pcap header pkthdr_t pktHdr; - char pkt_header[16]; while(1) { try { - fs.read(pkt_header, sizeof(pkt_header)); + fs.read((char*)&pktHdr, sizeof(pkthdr_t)); if ((fs.rdstate() & std::ifstream::failbit) != 0) { if ( (fs.rdstate() & std::ifstream::eofbit) != 0 ) { std::cout << "reach the end of pcap file!" << std::endl; @@ -130,16 +129,12 @@ int main(int argc, const char* argv[]) { std::cout << "Exception read file, " << e.what() << std::endl; return 1; } + if (isBigEndian) { - pktHdr.tv_sec = ntohl(*((uint32_t*)pkt_header)); - pktHdr.tv_usec = ntohl(*((uint32_t*)(pkt_header+4))); - pktHdr.caplen = ntohl(*((uint32_t*)(pkt_header+8))); - pktHdr.len = ntohl(*((uint32_t*)(pkt_header+12))); - } else { - pktHdr.tv_sec = *((uint32_t*)pkt_header); - pktHdr.tv_usec = *((uint32_t*)(pkt_header+4)); - pktHdr.caplen = *((uint32_t*)(pkt_header+8)); - pktHdr.len = *((uint32_t*)(pkt_header+12)); + pktHdr.tv_sec = ntohl(pktHdr.tv_sec); + pktHdr.tv_usec = ntohl(pktHdr.tv_usec); + pktHdr.caplen = ntohl(pktHdr.caplen); + pktHdr.len = ntohl(pktHdr.len); } // read pcap diff --git a/tools/gredump.cpp b/tools/gredump.cpp index 05911f1b4..9f2c13a82 100644 --- a/tools/gredump.cpp +++ b/tools/gredump.cpp @@ -121,7 +121,8 @@ void PcapHanler(GreHandleBuff *buff, const struct pcap_pkthdr *h, const uint8_t std::memcpy((void*)(cache->ipfrag_buff + fragOffset * 8), p, (size_t)nCount); cache->pkthdr.len += nCount - 8; cache->pkthdr.caplen += nCount - 8; - keybit = ntohl(*((uint32_t*)(cache->ipfrag_buff+4))); + memcpy(&keybit, cache->ipfrag_buff + 4, sizeof(uint32_t)); + keybit = ntohl(keybit); if (buff->grekey==0 || buff->grekey==keybit) { pcap_dump((u_char*)buff->dumper, &cache->pkthdr, (const uint8_t*)(cache->ipfrag_buff + 8)); buff->dumpCount++; @@ -225,7 +226,6 @@ int main(int argc, const char* argv[]) { return 1; } - int ret; char errbuf[PCAP_ERRBUF_SIZE]; pcap_t* pcap_handle; @@ -239,7 +239,7 @@ int main(int argc, const char* argv[]) { auto pcapGuard = MakeGuard([pcap_handle]() { pcap_close(pcap_handle); }); - ret = pcap_activate(pcap_handle); + int ret = pcap_activate(pcap_handle); if (ret != 0) { std::cerr << "Capture error: " << pcap_statustostr(ret) << std::endl; return 1; @@ -327,7 +327,7 @@ int main(int argc, const char* argv[]) { nCount = vm["count"].as(); } - ret = pcap_loop(pcap_handle, nCount, [](uint8_t *user, const struct pcap_pkthdr *h, const uint8_t *data) { + pcap_loop(pcap_handle, nCount, [](uint8_t *user, const struct pcap_pkthdr *h, const uint8_t *data) { GreHandleBuff* buff = (GreHandleBuff*)user; PcapHanler(buff, h, data); }, (uint8_t*)&grehandlebuff); diff --git a/tools/vxlandump.cpp b/tools/vxlandump.cpp new file mode 100644 index 000000000..6cfd24d91 --- /dev/null +++ b/tools/vxlandump.cpp @@ -0,0 +1,163 @@ +#ifdef WIN32 +#include +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include "scopeguard.h" +#include "versioninfo.h" + +#define VXLAN_PORT 4789 +int g_break_loop = 0; + +int vxlan_frame_match(const void* data, int size, uint32_t vni) +{ + if(size < 8) + return -1; + if(ntohl(((uint32_t*)data)[0]) == 0x08000000 && + (ntohl(((uint32_t*)data)[1]) >> 8) == vni) + return 0; + return -1; +} + +int main(int argc, const char* argv[]) { + boost::program_options::options_description desc("Allowed options"); + desc.add_options() + ("version,v", "show version.") + ("help,h", "show help.") + ("vni,n", boost::program_options::value()->value_name("VNI"), "vxlan vni filter.") + ("output,o", boost::program_options::value()->value_name("OUT_PCAP"), "output pcap file"); + + boost::program_options::variables_map vm; + uint32_t vni; + int sock; + pcap_t* cap; + pcap_dumper_t* dump; + sockaddr_in addr; + int noblock; + socklen_t addr_len; + timeval timeout; + fd_set rset; + std::vector buff; + int ret; + pcap_pkthdr hdr; + uint64_t capture_cnt; + uint64_t drop_cnt; + uint64_t dump_cnt; + + try { + boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm); + boost::program_options::notify(vm); + } catch (boost::program_options::error& e) { + std::cerr << "error: " << e.what() << std::endl; + return 1; + } + + // help + if (vm.count("help")) { + std::cout << desc << std::endl; + return 0; + } + + // version + if (vm.count("version")) { + showVersion(); + return 0; + } + + if(!vm.count("vni")) + { + std::cerr << "must set vni option!" << std::endl; + return -1; + } + vni = vm["vni"].as(); + + if (!vm.count("output")) { + std::cerr << "must set output option!" << std::endl; + return -1; + } + + if(!(cap = pcap_open_dead(DLT_EN10MB, UINT16_MAX))) + { + std::cerr << "pcap_open_dead() failed!" << std::endl; + return -1; + } + if(!(dump = pcap_dump_open(cap, vm["output"].as().c_str()))) + { + pcap_close(cap); + std::cerr << "pcap_dump_open() failed!" << std::endl; + return -1; + } + if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + pcap_dump_close(dump); + pcap_close(cap); + std::cerr << "socket() failed!" << std::endl; + return -1; + } + memset(&addr, 0, sizeof(addr)); + addr.sin_port = htons(VXLAN_PORT); + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_family = AF_INET; + if(bind(sock, (const sockaddr*)&addr, sizeof(addr)) < 0) + { + close(sock); + pcap_dump_close(dump); + pcap_close(cap); + return -1; + } + + noblock = 1; + setsockopt(sock, SOL_SOCKET, SOCK_NONBLOCK, &noblock, sizeof(noblock)); + + buff.resize(UINT16_MAX); + + std::signal(SIGINT, [](int){ + g_break_loop = 1; + }); + std::signal(SIGTERM, [](int){ + g_break_loop = 1; + }); + + capture_cnt = 0; + drop_cnt = 0; + dump_cnt = 0; + + for(;!g_break_loop;) + { + timeout.tv_sec = 0; + timeout.tv_usec = 50000; + FD_ZERO(&rset); + FD_SET(sock, &rset); + if(select(sock + 1, &rset, 0, 0, &timeout) > 0) + { + addr_len = sizeof(addr); + if((ret = recvfrom(sock, &*buff.begin(), UINT16_MAX, 0, (sockaddr*)&addr, &addr_len)) > 0) + { + ++capture_cnt; + if(vxlan_frame_match(&*buff.begin(), ret, vni) < 0) + { + ++drop_cnt; + } + else + { + ++dump_cnt; + ret -= 8; + hdr.caplen = hdr.len = ret; + gettimeofday(&hdr.ts, 0); + pcap_dump((u_char*)dump, &hdr, &*buff.begin() + 8); + } + } + } + } + std::cout << "Statis Result:" << std::endl; + std::cout << "Capture Packets Count: " << capture_cnt << std::endl; + std::cout << "Drop Not Udp(vxlan) Packets Count: " << drop_cnt << std::endl; + std::cout << "Dump Packets Count: " << dump_cnt << std::endl; + return 0; +} \ No newline at end of file