Commit 0d2ea98f authored by Nawasan Wisitsingkhon's avatar Nawasan Wisitsingkhon

read code

parents
target
Cargo.lock
*.log
language: rust
rust:
- stable
- beta
- nightly
after_success: |
[ "$TRAVIS_RUST_VERSION" = stable ] &&
[ "$TRAVIS_BRANCH" = master ] &&
[ "$TRAVIS_PULL_REQUEST" = false ] &&
cargo doc &&
echo "<meta http-equiv=refresh content=0;url=`echo $TRAVIS_REPO_SLUG | cut -d '/' -f 2`/index.html>" > target/doc/index.html &&
curl https://raw.githubusercontent.com/kmcallister/travis-doc-upload/master/travis-doc-upload.sh | sh
[package]
name = "rust_ofp"
version = "0.2.1"
authors = ["Sam Baxter <sbaxter@cs.umass.edu>"]
description = "Rust OpenFlow 0x01 Protocol and Controller Framework"
documentation = "https://baxtersa.github.io/rust_ofp/docs"
repository = "https://github.com/baxtersa/rust_ofp"
readme = "README.md"
keywords = ["SDN", "Networking", "OpenFlow"]
license = "MIT"
exclude = [
"scripts/*",
".travis.yml",
".gitignore",
]
[lib]
name = "rust_ofp"
path = "src/lib.rs"
[[bin]]
name = "rust_ofp_controller"
path = "src/main.rs"
[dependencies]
byteorder = "1.0.0"
hex-literal = "0.4.1"
md5 = "0.7.0"
MIT License
Copyright (c) 2016 Sam Baxter
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.
rust_ofp [![Build Status](https://travis-ci.org/baxtersa/rust_ofp.svg?branch=master)](https://travis-ci.org/baxtersa/rust_ofp) [![](http://meritbadge.herokuapp.com/rust_ofp)](https://crates.io/crates/rust_ofp)
===
OpenFlow 1.0 protocol and controller in Rust.
---
`rust_ofp` aims to implement the OpenFlow1.0 protocol, for purposes of prototyping SDN systems in Rust. In the future, this may grow to support other OpenFlow specifications (namely 1.3), and others protocols entirely.
I'm drawing heavily on inspiration and code structure from the [frenetic-lang](https://github.com/frenetic-lang) project, due to my familiarity with it. I hope that Rust will enable a more natural implementation of the low-level protocol than OCaml + CStructs, and true parallelism will allow for higher controller performance and a simpler event loop.
See my blog post on the crate [here](http://baxtersa.github.io/2016/12/30/rust-openflow-0x01.html)!
Building
---
`rust_ofp` is composed of a Rust library implementing the OpenFlow 1.0 protocol, and a `rust_ofp_controller` binary that currently acts as little more than an echo server for SDN configurations. It can be built and run by the normal means for Rust projects.
```bash
cd path/to/rust_ofp
cargo build
cargo run
```
Testing
---
I'm performing all correctness evaluation in [mininet](https://mininet.org) for the time being. Mininet offers quick feedback, as much scalability as I need for now, and should properly support OpenFlow 1.0 (and other protocols). There is no reason correctness in mininet shouldn't transfer to physical hardware as well, and maybe one day I'll get around to testing out that hypothesis.
Anyway, testing the controller binary is pretty straightforward, assuming mininet is installed.
In one terminal
```bash
cd path/to/rust_ofp
cargo run
```
In another terminal
```bash
sudo mn --controller=remote
```
The terminal running `rust_ofp_controller` will occasionally print some things out, logging a rough idea of the types of messages it receives, and behaviors it performs.
The mininet terminal should launch an interactive shell with the typical mininet utilities.
Currently, the test executable for `rust_ofp` implements MAC learning, so as hosts ping eachother, the controller installs forwarding rules on switches rather than routing all packets through the controller.
Documentation
---
Travis CI automatically uploads source documentation generated by `cargo doc`.
- [`rust_ofp`](https://baxtersa.github.io/rust_ofp/docs)
- [`rust_ofp_controller`](https://baxtersa.github.io/rust_ofp/docs/rust_ofp_controller)
ToDo
---
Some parts of the OpenFlow 1.0 standard remain unimplemented. Notably, `rust_ofp` does not currently implement the following message codes:
- `OFPT_VENDOR`
- `OFPT_GET_CONFIG_REQUEST/OFPT_GET_CONFIG_REPLY`
- `OFPT_SET_CONFIG`
- `OFPT_PORT_MOD`
- `OFPT_STATS_REQUEST/OFPT_STATS_REPLY`
- `OFPT_QUEUE_GET_CONFIG_REQUEST/OFPT_QUEUE_GET_CONFIG_REPLY`
The current controller executable is a minimal wrapper around the protocol that doesn't dynamically handle any rule configuration. Future goals for the controller include:
- A GTK GUI for configuring and querying an SDN dynamically.
- A compiler from some higher-level abstraction to install a forwarding policy other than a global `DROP` on launch.
- [Consistent Updates](http://www.cs.cornell.edu/~jnfoster/papers/frenetic-consistent-updates.pdf) for dynamically updating an SDN's global forwarding policy.
Ok(TcpStream { addr: 127.0.0.1:6633, peer: 127.0.0.1:51254, fd: 4 })
=================== connection =======================
send : [1, 0, 0, 8, 0, 0, 0, 0]
get : [0, 0, 0, 0, 0, 0, 0, 0]
Connection closed reading header.
======================================================
Ok(TcpStream { addr: 127.0.0.1:6633, peer: 127.0.0.1:51264, fd: 5 })
=================== connection =======================
send : [1, 0, 0, 8, 0, 0, 0, 0]
get : [1, 0, 0, 8, 0, 0, 0, 4]
Hello!
send : [1, 5, 0, 8, 0, 0, 0, 4]
get : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : [1, 6, 1, 16, 0, 0, 0, 4]
FeaturesResp
get : [1, 10, 0, 128, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 117, 3, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 176, 248, 184, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
get : [1, 10, 0, 104, 0, 0, 0, 0]
PacketIn
Flooding to 56298414538756
send : [1, 13, 0, 110, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 4, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4, 135, 0, 152, 147, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 14, 1, 251, 164, 87, 192, 129, 29]
get : [1, 10, 0, 104, 0, 0, 0, 0]
PacketIn
Flooding to 56298414538755
send : [1, 13, 0, 110, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 3, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3, 135, 0, 199, 32, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 14, 1, 77, 191, 211, 238, 132, 73]
get : [1, 10, 0, 128, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 134, 87, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 145, 231, 134, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
get : [1, 10, 0, 128, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 248, 131, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 180, 117, 54, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
get : [1, 10, 0, 128, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 174, 147, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 128, 191, 89, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
get : [1, 10, 0, 104, 0, 0, 0, 0]
PacketIn
Flooding to 56298414538754
send : [1, 13, 0, 110, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2, 135, 0, 16, 86, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 14, 1, 106, 43, 178, 2, 64, 150]
get : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 7, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
get : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 44, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1]
get : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 1, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
get : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 38, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 4]
get : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 7, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
get : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 3, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
get : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 40, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 3]
get : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 3, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
get : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 1, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
get : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 5, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
get : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 42, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2]
get : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 5, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
get : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 38, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 4]
get : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : [1, 12, 0, 64, 0, 0, 0, 0]
Connection closed reading header.
======================================================
\ No newline at end of file
Ok(TcpStream { addr: 127.0.0.1:6633, peer: 127.0.0.1:47114, fd: 4 })
=================== connection =======================
send : 8bytes : [1, 0, 0, 8, 0, 0, 0, 0]
get : 8bytes : [0, 0, 0, 0, 0, 0, 0, 0]
Connection closed reading header.
======================================================
Ok(TcpStream { addr: 127.0.0.1:6633, peer: 127.0.0.1:47116, fd: 5 })
=================== connection =======================
send : 8bytes : [1, 0, 0, 8, 0, 0, 0, 0]
get : 8bytes : [1, 0, 0, 8, 0, 0, 0, 21]
Hello!
send : 8bytes : [1, 5, 0, 8, 0, 0, 0, 21]
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : 8bytes : [1, 6, 1, 16, 0, 0, 0, 21]
FeaturesResp
get : 8bytes : [1, 10, 0, 104, 0, 0, 0, 0]
PacketIn
Flooding to 56298414538754
send : 110bytes : [1, 13, 0, 110, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2, 135, 0, 128, 17, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 14, 1, 235, 122, 222, 110, 35, 31]
get : 8bytes : [1, 10, 0, 104, 0, 0, 0, 0]
PacketIn
Flooding to 56298414538753
send : 110bytes : [1, 13, 0, 110, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 1, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1, 135, 0, 65, 15, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 14, 1, 230, 108, 213, 14, 112, 145]
get : 8bytes : [1, 10, 0, 104, 0, 0, 0, 0]
PacketIn
Flooding to 56298414538755
send : 110bytes : [1, 13, 0, 110, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 3, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3, 135, 0, 253, 168, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 14, 1, 106, 160, 252, 79, 8, 127]
get : 8bytes : [1, 10, 0, 128, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 134bytes : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 168, 52, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 157, 197, 154, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
get : 8bytes : [1, 10, 0, 104, 0, 0, 0, 0]
PacketIn
Flooding to 56298414538756
send : 110bytes : [1, 13, 0, 110, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 4, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4, 135, 0, 61, 159, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 14, 1, 118, 137, 199, 105, 241, 131]
get : 8bytes : [1, 10, 0, 128, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 134bytes : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 37, 204, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 2, 72, 160, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
get : 8bytes : [1, 10, 0, 128, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 134bytes : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 191, 205, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 46, 174, 113, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
get : 8bytes : [1, 10, 0, 128, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 134bytes : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 117, 98, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 2, 249, 10, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 5, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 42, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 5, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 7, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 44, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 3, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 40, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 3]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 7, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 3, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 1, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 38, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 4]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 1, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 42, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 40, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 3]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 44, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 38, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 4]
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
Connection closed reading header.
======================================================
Ok(TcpStream { addr: 127.0.0.1:6633, peer: 127.0.0.1:36988, fd: 4 })
=================== connection =======================
send : 8bytes : [1, 0, 0, 8, 0, 0, 0, 0]
get : 8bytes : [0, 0, 0, 0, 0, 0, 0, 0]
Connection closed reading header.
======================================================
Ok(TcpStream { addr: 127.0.0.1:6633, peer: 127.0.0.1:36992, fd: 4 })
=================== connection =======================
=================== Hello ============================
send : 8bytes : [1, 0, 0, 8, 0, 0, 0, 0]
get : 8bytes : [1, 0, 0, 8, 0, 0, 0, 22]
Hello!
======================================================
=================== PortMod ==========================
# 5 is PortMod
# 6 is groupMod
send : 8bytes : [1, 5, 0, 8, 0, 0, 0, 22]
get : 8bytes : [1, 6, 1, 16, 0, 0, 0, 22]
=================== PortStatus =======================
# 12 is portStatus
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
=================== PacketIn =========================
get : 8bytes : [1, 10, 0, 128, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 134bytes : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 106, 170, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 139, 3, 55, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
get : 8bytes : [1, 10, 0, 104, 0, 0, 0, 0]
PacketIn
Flooding to 56298414538755
send : 110bytes : [1, 13, 0, 110, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 3, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3, 135, 0, 41, 189, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 14, 1, 212, 137, 203, 127, 163, 81]
get : 8bytes : [1, 10, 0, 104, 0, 0, 0, 0]
PacketIn
Flooding to 56298414538753
send : 110bytes : [1, 13, 0, 110, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 1, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1, 135, 0, 35, 151, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 14, 1, 43, 77, 12, 218, 17, 94]
get : 8bytes : [1, 10, 0, 128, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 134bytes : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 5, 222, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 190, 103, 210, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
get : 8bytes : [1, 10, 0, 104, 0, 0, 0, 0]
PacketIn
Flooding to 56298414538756
send : 110bytes : [1, 13, 0, 110, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 4, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4, 135, 0, 8, 68, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 14, 1, 19, 57, 185, 119, 152, 33]
get : 8bytes : [1, 10, 0, 128, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 134bytes : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 203, 197, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 84, 162, 85, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
get : 8bytes : [1, 10, 0, 128, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 134bytes : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 111, 160, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 248, 253, 212, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 5, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 42, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 5, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 3, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 40, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 3]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 7, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 44, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 1, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 38, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 4]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 1, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 3, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 7, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 42, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 38, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 4]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 44, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 40, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 3]
get : 8bytes : [1, 2, 0, 8, 0, 0, 0, 0]
send : 8bytes : [1, 3, 0, 8, 0, 0, 0, 0]
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
PortStatus
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
Connection closed reading header.
======================================================
\ No newline at end of file
Ok(TcpStream { addr: 127.0.0.1:6633, peer: 127.0.0.1:33612, fd: 4 })
=================== connection =======================
send : 8bytes : [1, 0, 0, 8, 0, 0, 0, 0]
get : 8bytes : [0, 0, 0, 0, 0, 0, 0, 0]
Connection closed reading header.
======================================================
Ok(TcpStream { addr: 127.0.0.1:6633, peer: 127.0.0.1:33628, fd: 4 })
=================== connection =======================
=================== Hello ============================
send : 8bytes : [1, 0, 0, 8, 0, 0, 0, 0]
get : 8bytes : [1, 0, 0, 8, 0, 0, 0, 24]
data: []
Hello!
======================================================
=================== PortMod ==========================
# 5 is PortMod
# 6 is groupMod
send : 8bytes : [1, 5, 0, 8, 0, 0, 0, 24]
get : 8bytes : [1, 6, 1, 16, 0, 0, 0, 24]
data: [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 254, 0, 0, 0, 0, 0, 0, 199, 0, 0, 15, 255, 255, 254, 194, 114, 216, 164, 186, 66, 115, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 222, 11, 44, 35, 244, 30, 115, 49, 45, 101, 116, 104, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 110, 88, 91, 105, 85, 17, 115, 49, 45, 101, 116, 104, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 166, 3, 72, 109, 57, 178, 115, 49, 45, 101, 116, 104, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 54, 119, 181, 50, 166, 39, 115, 49, 45, 101, 116, 104, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
=================== PortStatus ========================
# 12 is port status
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
data: [2, 0, 0, 0, 0, 0, 0, 0, 255, 254, 194, 114, 216, 164, 186, 66, 115, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
=================== packetIn start =========================
# 10 is packetIn
get : 8bytes : [1, 10, 0, 104, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 86, 0, 3, 0, 0, 51, 51, 255, 0, 0, 3, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3, 135, 0, 83, 33, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 14, 1, 6, 37, 88, 12, 187, 197]
PacketIn
Flooding to 56298414538755
# after 10 (PacketIn) send group
send : 110bytes : [1, 13, 0, 110, 0, 0, 0, 0,
255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 3, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3, 135, 0, 83, 33, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 14, 1, 6, 37, 88, 12, 187, 197]
get : 8bytes : [1, 10, 0, 128, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 110, 0, 2, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 120, 30, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 49, 246, 30, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
PacketIn
Flooding to 56294136348694
send : 134bytes : [1, 13, 0, 134, 0, 0, 0, 0,
255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 120, 30, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 49, 246, 30, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
get : 8bytes : [1, 10, 0, 104, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 86, 0, 2, 0, 0, 51, 51, 255, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2, 135, 0, 117, 45, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 14, 1, 13, 204, 23, 12, 211, 20]
PacketIn
Flooding to 56298414538754
send : 110bytes : [1, 13, 0, 110, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2, 135, 0, 117, 45, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 14, 1, 13, 204, 23, 12, 211, 20]
get : 8bytes : [1, 10, 0, 104, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 86, 0, 4, 0, 0, 51, 51, 255, 0, 0, 4, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4, 135, 0, 142, 207, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 14, 1, 254, 255, 104, 231, 118, 95]
PacketIn
Flooding to 56298414538756
send : 110bytes : [1, 13, 0, 110, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 4, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4, 135, 0, 142, 207, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 14, 1, 254, 255, 104, 231, 118, 95]
get : 8bytes : [1, 10, 0, 128, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 110, 0, 4, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 58, 111, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 219, 51, 34, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
PacketIn
Flooding to 56294136348694
send : 134bytes : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 58, 111, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 219, 51, 34, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
get : 8bytes : [1, 10, 0, 104, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 86, 0, 1, 0, 0, 51, 51, 255, 0, 0, 1, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1, 135, 0, 107, 172, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 14, 1, 231, 6, 15, 229, 10, 132]
PacketIn
Flooding to 56298414538753
send : 110bytes : [1, 13, 0, 110, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 255, 0, 0, 1, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 32, 58, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1, 135, 0, 107, 172, 0, 0, 0, 0, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 14, 1, 231, 6, 15, 229, 10, 132]
get : 8bytes : [1, 10, 0, 128, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 110, 0, 1, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 110, 130, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 8, 255, 228, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
PacketIn
Flooding to 56294136348694
send : 134bytes : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 110, 130, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 8, 255, 228, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
get : 8bytes : [1, 10, 0, 128, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 110, 0, 3, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 164, 231, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 15, 201, 118, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
PacketIn
Flooding to 56294136348694
send : 134bytes : [1, 13, 0, 134, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 56, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 164, 231, 0, 0, 0, 2, 3, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 15, 201, 118, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 90, 0, 3, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 3, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 3, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 70, 0, 3, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 40, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 3]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 40, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 3]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 90, 0, 2, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 5, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 5, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 70, 0, 2, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 42, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 42, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 90, 0, 4, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 1, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 1, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 70, 0, 4, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 38, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 4]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 38, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 4]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 90, 0, 2, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 5, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 5, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 2]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 90, 0, 1, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 7, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 7, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 70, 0, 1, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 44, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 44, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 90, 0, 1, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 7, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 7, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 1]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 90, 0, 4, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 1, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 1, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 4]
get : 8bytes : [1, 10, 0, 108, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 90, 0, 3, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 3, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
PacketIn
Flooding to 56294136348694
send : 114bytes : [1, 13, 0, 114, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 22, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 36, 0, 1, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 58, 0, 5, 2, 0, 0, 1, 0, 143, 0, 112, 3, 0, 0, 0, 1, 4, 0, 0, 0, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 3]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 70, 0, 3, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 40, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 3]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 40, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 3]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 70, 0, 4, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 38, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 4]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 38, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 4]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 70, 0, 2, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 42, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 42, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 70, 0, 1, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 44, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 44, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1]
get : 8bytes : [1, 2, 0, 8, 0, 0, 0, 0]
data: []
send : 8bytes : [1, 3, 0, 8, 0, 0, 0, 0]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 70, 0, 3, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 40, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 3]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 3, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 40, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 3]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 70, 0, 4, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 38, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 4]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 4, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 4, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 38, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 4]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 70, 0, 2, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 42, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 2, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 42, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 2]
get : 8bytes : [1, 10, 0, 88, 0, 0, 0, 0]
data: [255, 255, 255, 255, 0, 70, 0, 1, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 44, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1]
PacketIn
Flooding to 56294136348674
send : 94bytes : [1, 13, 0, 94, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 0, 8, 0, 0, 0, 8, 255, 252, 0, 0, 51, 51, 0, 0, 0, 2, 0, 0, 0, 0, 0, 1, 134, 221, 96, 0, 0, 0, 0, 16, 58, 255, 254, 128, 0, 0, 0, 0, 0, 0, 2, 0, 0, 255, 254, 0, 0, 1, 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 133, 0, 123, 44, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1]
get : 8bytes : [1, 2, 0, 8, 0, 0, 0, 0]
data: []
send : 8bytes : [1, 3, 0, 8, 0, 0, 0, 0]
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
data: [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 110, 88, 91, 105, 85, 17, 115, 49, 45, 101, 116, 104, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
PortStatus
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
data: [1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 166, 3, 72, 109, 57, 178, 115, 49, 45, 101, 116, 104, 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
PortStatus
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
data: [1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 54, 119, 181, 50, 166, 39, 115, 49, 45, 101, 116, 104, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
PortStatus
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
data: [1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 222, 11, 44, 35, 244, 30, 115, 49, 45, 101, 116, 104, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
PortStatus
get : 8bytes : [1, 12, 0, 64, 0, 0, 0, 0]
Connection closed reading header.
======================================================
\ No newline at end of file
PROJECT_NAME=docs
DOCS_REPO=baxtersa/rust_ofp.git
SSH_KEY_TRAVIS_ID=6b1a22a7fe81
\ No newline at end of file
/// Set bit `bit` of `x` on if `toggle` is true, otherwise off.
pub fn bit(bit: u64, x: u64, toggle: bool) -> u64 {
if toggle {
x | (1 << bit)
} else {
x & !(1 << bit)
}
}
/// Test whether bit `bit` of `x` is set.
pub fn test_bit(bit: u64, x: u64) -> bool {
(x >> bit) & 1 == 1
}
use std::collections::HashMap;
use std::net::TcpStream;
use rust_ofp::ofp_controller::openflow0x01::OF0x01Controller;
use rust_ofp::openflow0x01::{Action, PacketIn, PacketOut, Pattern, PseudoPort, SwitchFeatures};
use rust_ofp::openflow0x01::message::{add_flow, parse_payload};
/// Implements L2 learning switch functionality. Switches forward packets to the
/// learning controller, which will examine the packet and learn the source-port
/// mapping. If the controller already knows the destination location, it pushes
/// a flow entry down to the switch that matches traffic between the packet's
/// source and destination.
///
/// Abstractly, a learning switch can be thought of in terms of two logically
/// distinct components.
///
/// - A _Learning Module_ that builds a map from host MAC addresses to the
/// switch port on which they are connected.
///
/// - A _Routing Module_ that performs traffic routing. If the switch receives
/// a packet which the learning module has learned of the destination location,
/// it forwards the packet directly on the associated port. If the location of
/// the destination is unknown, it floods the packet out all ports.
pub struct LearningSwitch {
known_hosts: HashMap<u64, u16>,
}
impl LearningSwitch {
fn learning_packet_in(&mut self, pkt: &PacketIn) {
let pk = parse_payload(&pkt.input_payload);
self.known_hosts.insert(pk.dl_src, pkt.port);
}
fn routing_packet_in(&mut self, sw: u64, pkt: PacketIn, stream: &mut TcpStream) {
let pk = parse_payload(&pkt.input_payload);
let pkt_dst = pk.dl_dst;
let pkt_src = pk.dl_src;
// ดึง port ที่เก็บไว้ โดยใส่ mac ปลายทาง
let out_port = self.known_hosts.get(&pkt_dst);
match out_port {
Some(p) => {
let src_port = pkt.port;
let mut src_dst_match = Pattern::match_all();
src_dst_match.dl_dst = Some(pkt_dst);
src_dst_match.dl_src = Some(pkt_src);
let mut dst_src_match = Pattern::match_all();
dst_src_match.dl_dst = Some(pkt_src);
dst_src_match.dl_src = Some(pkt_dst);
println!("Installing rule for host {:?} to {:?}.", pkt_src, pkt_dst);
let actions = vec![Action::Output(PseudoPort::PhysicalPort(*p))];
Self::send_flow_mod(sw, 0, add_flow(10, src_dst_match, actions), stream);
println!("Installing rule for host {:?} to {:?}.", pkt_dst, pkt_src);
let actions = vec![Action::Output(PseudoPort::PhysicalPort(src_port))];
Self::send_flow_mod(sw, 0, add_flow(10, dst_src_match, actions), stream);
let pkt_out = PacketOut {
output_payload: pkt.input_payload,
port_id: None,
apply_actions: vec![Action::Output(PseudoPort::PhysicalPort(*p))],
};
Self::send_packet_out(sw, 0, pkt_out, stream)
}
None => {
println!("Flooding to {:?}", pkt_dst);
let pkt_out = PacketOut {
output_payload: pkt.input_payload,
port_id: None,
apply_actions: vec![Action::Output(PseudoPort::AllPorts)],
};
Self::send_packet_out(sw, 0, pkt_out, stream)
}
}
}
}
impl OF0x01Controller for LearningSwitch {
fn new() -> LearningSwitch {
LearningSwitch { known_hosts: HashMap::new() }
}
fn switch_connected(&mut self, _: u64, _: SwitchFeatures, _: &mut TcpStream) {}
fn switch_disconnected(&mut self, _: u64) {}
fn packet_in(&mut self, sw: u64, _: u32, pkt: PacketIn, stream: &mut TcpStream) {
self.learning_packet_in(&pkt);
self.routing_packet_in(sw, pkt, stream);
}
}
#![crate_name = "rust_ofp"]
#![crate_type = "lib"]
extern crate byteorder;
pub mod learning_switch;
mod bits;
pub mod ofp_controller;
pub mod ofp_header;
pub mod ofp_message;
pub mod openflow0x01;
pub mod packet;
mod rust_ofp {
pub use super::*;
}
use std::io::{BufRead, Cursor, Error, Read, Write};
use std::net::{TcpListener, TcpStream};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use rust_ofp::learning_switch::LearningSwitch;
use rust_ofp::ofp_controller::OfpController;
extern crate byteorder;
extern crate rust_ofp;
struct packetIn {
buf_id: Option<i32>,
payload: Vec<u8>,
total_len: u16,
port: u16,
reason: u8,
}
fn packetin_payload(buf:&mut Vec<u8>) -> Result<packetIn, Error> {
let mut packet = Cursor::new(buf.to_vec());
let buf_id = match packet.read_i32::<BigEndian>()? {
-1 => None,
n => Some(n),
};
let total_len = packet.read_u16::<BigEndian>()?;
let port = packet.read_u16::<BigEndian>()?;
let reason = packet.read_u8()?;
packet.consume(1);
let payload = packet.fill_buf()?.to_vec();
Ok(packetIn {
buf_id: buf_id,
payload: payload,
port: port,
reason: reason,
total_len: total_len,
})
}
fn send_hello(stream: &mut TcpStream) {
let mut buf: Vec<u8> = Vec::new();
buf.write_u8(1).unwrap();
buf.write_u8(0).unwrap();
buf.write_u16::<BigEndian>(8).unwrap();
buf.write_u32::<BigEndian>(0).unwrap();
println!("send: {:?}", buf);
stream.write_all(&buf).unwrap();
}
fn feture_req(stream: &mut TcpStream, xid: u32) -> Result<(), std::io::Error> {
let mut buf: Vec<u8> = Vec::new();
buf.write_u8(1)?;
buf.write_u8(5)?;
buf.write_u16::<BigEndian>(8)?;
buf.write_u32::<BigEndian>(xid)?;
println!("send: {:?}", buf);
stream.write_all(&buf)?;
Ok(())
}
fn main() -> Result<(), std::io::Error> {
let listener = TcpListener::bind(("127.0.0.1", 6633)).unwrap();
let mut buf = vec![0u8; 8];
for stream in listener.incoming() {
println!("{:?}", stream);
match stream {
Ok(mut stream) => {
// std::thread::spawn(move || {
println!("=================== connection =======================");
// LearningSwitch::handle_client_connected(&mut stream);
// continue;
// after tcp is connected, it will send hello message
send_hello(&mut stream);
// loop for receive data
loop {
// first receive with Openflow header 64 bit to buf
let res = stream.read(&mut buf);
match res {
Ok(v) if v > 0 => {
let mut packet = Cursor::new(buf.to_vec());
println!("buf: {:?}", packet);
// split data from header
let _version = packet.read_u8().unwrap();
let message = packet.read_u8().unwrap();
// length is only payload size to receive
let length = packet.read_u16::<BigEndian>().unwrap() - 8;
let xid = packet.read_u32::<BigEndian>().unwrap();
// message_body is var to receive payload if it has
// and assign size by length
let mut message_body = vec![0u8; length as usize];
stream.read(&mut message_body)?;
match message {
// 0 is Hello message
0 => {
// after get Hello, send fetureReq
feture_req(&mut stream, xid)?;
}
10 => {
let payload = packetin_payload(&mut buf)?;
}
_ => {
println!("others message");
}
}
}
Ok(_) | Err(_) => break,
}
}
println!("======================================================");
// });
}
Err(_) => {
// connection failed
panic!("Connection failed")
}
}
}
Ok(())
}
use std::net::TcpStream;
use rust_ofp::ofp_message::OfpMessage;
/// OpenFlow Controller
///
/// Version-agnostic API for implementing an OpenFlow controller.
pub trait OfpController {
/// OpenFlow message type supporting the same protocol version as the controller.
type Message: OfpMessage;
/// Send a message to the node associated with the given `TcpStream`.
fn send_message(u32, Self::Message, &mut TcpStream);
/// Perform handshake and begin loop reading incoming messages from client stream.
fn handle_client_connected(&mut TcpStream);
}
pub mod openflow0x01 {
use super::*;
use std::hash::{DefaultHasher, Hash, Hasher};
use std::mem::size_of_val;
use std::io::{Write, Read};
use std::marker::PhantomData;
use std::net::TcpStream;
use rust_ofp::ofp_header::OfpHeader;
use rust_ofp::ofp_message::OfpMessage;
use rust_ofp::openflow0x01::{FlowMod, PacketIn, PacketOut, SwitchFeatures};
use rust_ofp::openflow0x01::message::Message;
#[derive(Debug)]
struct ThreadState<Cntl> {
switch_id: Option<u64>,
phantom: PhantomData<Cntl>,
}
impl<Cntl: OF0x01Controller> ThreadState<Cntl> {
fn process_message(&mut self,
cntl: &mut Cntl,
xid: u32,
msg: Message,
stream: &mut TcpStream) {
match msg {
Message::Hello => Cntl::send_message(xid, Message::FeaturesReq, stream),
Message::Error(err) => println!("Error: {:?}", err),
Message::EchoRequest(bytes) => {
Cntl::send_message(xid, Message::EchoReply(bytes), stream)
}
Message::EchoReply(_) => (),
Message::FeaturesReq => (),
Message::FeaturesReply(feats) => {
if self.switch_id.is_some() {
panic!("Switch connection already received.")
}
self.switch_id = Some(feats.datapath_id);
Cntl::switch_connected(cntl, feats.datapath_id, feats, stream)
}
Message::FlowMod(_) => (),
Message::PacketIn(pkt) => {
Cntl::packet_in(cntl, self.switch_id.unwrap(), xid, pkt, stream)
}
Message::FlowRemoved(_) |
Message::PortStatus(_) |
Message::PacketOut(_) |
Message::BarrierRequest |
Message::BarrierReply => (),
}
}
fn switch_disconnected(&self, cntl: &mut Cntl) {
Cntl::switch_disconnected(cntl, self.switch_id.unwrap())
}
}
/// OpenFlow0x01 Controller API
///
/// OpenFlow 1.0-specific API for communicating between a controller and the dataplane.
pub trait OF0x01Controller: OfpController<Message = Message> {
/// Create a new Controller.
fn new() -> Self;
/// Callback invoked with `sw` when a switch with identifier `sw` connects to
/// the controller.
fn switch_connected(&mut self, sw: u64, feats: SwitchFeatures, stream: &mut TcpStream);
/// Callback invoked with `sw` when a switch with identifier `sw` disconnects
/// from the controller.
fn switch_disconnected(&mut self, sw: u64);
/// Callback invoked when a packet `pkt` with transaction ID `xid` from
/// switch `sw` arrives at the controller.
fn packet_in(&mut self, sw: u64, xid: u32, pkt: PacketIn, stream: &mut TcpStream);
/// Send packet `pkt` with transaction ID `xid` to switch `sw` from the controller.
fn send_packet_out(_: u64, xid: u32, pkt: PacketOut, stream: &mut TcpStream) {
Self::send_message(xid, Message::PacketOut(pkt), stream)
}
/// Send flowmod `flow` with transaction ID `xid` to switch `sw` from the controller.
fn send_flow_mod(_: u64, xid: u32, flow: FlowMod, stream: &mut TcpStream) {
Self::send_message(xid, Message::FlowMod(flow), stream)
}
/// Send barrier request with transaction ID `xid` to switch `sw` from the controller.
/// Guarantees switch `sw` processes messages prior to barrier before messages after.
fn send_barrier_request(_: u64, xid: u32, stream: &mut TcpStream) {
Self::send_message(xid, Message::BarrierRequest, stream)
}
}
impl<Controller: OF0x01Controller> OfpController for Controller {
type Message = Message;
fn send_message(xid: u32, message: Message, writer: &mut TcpStream) {
let raw_msg = Message::marshal(xid, message);
println!("send : {}bytes : {:?}", raw_msg.len(), raw_msg);
writer.write_all(&raw_msg).unwrap()
}
fn handle_client_connected(stream: &mut TcpStream) {
let mut cntl = Controller::new();
Controller::send_message(0, Message::Hello, stream);
let mut buf = [0u8; 8];
let mut thread_state = ThreadState::<Self> {
switch_id: None,
phantom: PhantomData,
};
loop {
let res = stream.read(&mut buf);
println!("get : {}bytes : {:?}", size_of_val(&buf), buf);
match res {
Ok(num_bytes) if num_bytes > 0 => {
let header = OfpHeader::parse(buf);
// ขนาดทั้งหมด ลบด้วย ขนาดของ header
let message_len = header.length() - OfpHeader::size();
let mut message_buf = vec![0; message_len];
// อ่านข้อมูลที่เหลือ จาก tcp โดยที่ การอ่านครั้งแรกคือ Header ขนาด 64 bytes
let _ = stream.read(&mut message_buf);
println!("data: {:?}", message_buf);
// message::parse สำหรับคำนวณว่าต้องตอบกลับเป็น message อะไร
// let mut hash = DefaultHasher::new();
// message_buf.hash(&mut hash);
// println!("data: {}", hash.finish());
let (xid, body) = Message::parse(&header, &message_buf);
thread_state.process_message(&mut cntl, xid, body, stream)
}
Ok(_) => {
println!("Connection closed reading header.");
break;
}
Err(e) => {
println!("{}", e);
thread_state.switch_disconnected(&mut cntl)
}
}
}
}
}
}
use std::io::Cursor;
use std::mem::{size_of, transmute};
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};
use rust_ofp::openflow0x01::MsgCode;
/// OpenFlow Header
///
/// The first fields of every OpenFlow message, no matter the protocol version.
/// This is parsed to determine version and length of the remaining message, so that
/// it can be properly handled.
#[repr(packed)]
pub struct OfpHeader {
version: u8,
typ: u8,
length: u16,
xid: u32,
}
impl OfpHeader {
/// Create an `OfpHeader` out of the arguments.
pub fn new(version: u8, typ: u8, length: u16, xid: u32) -> OfpHeader {
OfpHeader {
version: version,
typ: typ,
length: length,
xid: xid,
}
}
/// Return the byte-size of an `OfpHeader`.
pub fn size() -> usize {
size_of::<OfpHeader>()
}
/// Fills a message buffer with the header fields of an `OfpHeader`.
pub fn marshal(bytes: &mut Vec<u8>, header: OfpHeader) {
bytes.write_u8(header.version()).unwrap();
bytes.write_u8(header.type_code() as u8).unwrap();
bytes.write_u16::<BigEndian>(header.length() as u16).unwrap();
bytes.write_u32::<BigEndian>(header.xid()).unwrap();
}
/// Takes a message buffer (sized for an `OfpHeader`) and returns an `OfpHeader`.
pub fn parse(buf: [u8; 8]) -> Self {
let mut bytes = Cursor::new(buf.to_vec());
OfpHeader {
version: bytes.read_u8().unwrap(),
typ: bytes.read_u8().unwrap(),
length: bytes.read_u16::<BigEndian>().unwrap(),
xid: bytes.read_u32::<BigEndian>().unwrap(),
}
}
/// Return the `version` field of a header.
pub fn version(&self) -> u8 {
self.version
}
/// Return the OpenFlow message type code of a header.
/// # Safety
///
/// The `typ` field of the `self` header is expected to be a `u8` within the
/// defined range of the `MsgCode` enum.
pub fn type_code(&self) -> MsgCode {
unsafe { transmute(self.typ) }
}
/// Return the `length` field of a header. Includes the length of the header itself.
pub fn length(&self) -> usize {
self.length as usize
}
/// Return the `xid` field of a header, the transaction id associated with this packet.
/// Replies use the same id to facilitate pairing.
pub fn xid(&self) -> u32 {
self.xid
}
}
use ofp_header::OfpHeader;
/// OpenFlow Message
///
/// Version-agnostic API for handling OpenFlow messages at the byte-buffer level.
pub trait OfpMessage {
/// Return the byte-size of an `OfpMessage`.
fn size_of(&Self) -> usize;
/// Create an `OfpHeader` for the given transaction id and OpenFlow message.
fn header_of(u32, &Self) -> OfpHeader;
/// Return a marshaled buffer containing an OpenFlow header and the message `msg`.
fn marshal(u32, Self) -> Vec<u8>;
/// Returns a pair `(u32, OfpMessage)` of the transaction id and OpenFlow message parsed from
/// the given OpenFlow header `header`, and buffer `buf`.
fn parse(&OfpHeader, &[u8]) -> (u32, Self);
}
use std::io::{BufRead, Cursor, Read, Write};
use std::mem::{size_of, transmute};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use bits::*;
use packet::{bytes_of_mac, mac_of_bytes};
/// OpenFlow 1.0 message type codes, used by headers to identify meaning of the rest of a message.
#[repr(u8)]
#[derive(Copy, Clone, Debug)]
pub enum MsgCode {
Hello,
Error,
EchoReq,
EchoResp,
Vendor,
FeaturesReq,
FeaturesResp,
GetConfigReq,
GetConfigResp,
SetConfig,
PacketIn,
FlowRemoved,
PortStatus,
PacketOut,
FlowMod,
PortMod,
StatsReq,
StatsResp,
BarrierReq,
BarrierResp,
QueueGetConfigReq,
QueueGetConfigResp,
}
/// Common API for message types implementing OpenFlow Message Codes (see `MsgCode` enum).
pub trait MessageType {
/// Return the byte-size of a message.
fn size_of(&Self) -> usize;
/// Parse a buffer into a message.
fn parse(buf: &[u8]) -> Self;
/// Marshal a message into a `u8` buffer.
fn marshal(Self, &mut Vec<u8>);
}
pub struct Mask<T> {
pub value: T,
pub mask: Option<T>,
}
/// Fields to match against flows.
pub struct Pattern {
pub dl_src: Option<u64>,
pub dl_dst: Option<u64>,
pub dl_typ: Option<u16>,
pub dl_vlan: Option<Option<u16>>,
pub dl_vlan_pcp: Option<u8>,
pub nw_src: Option<Mask<u32>>,
pub nw_dst: Option<Mask<u32>>,
pub nw_proto: Option<u8>,
pub nw_tos: Option<u8>,
pub tp_src: Option<u16>,
pub tp_dst: Option<u16>,
pub in_port: Option<u16>,
}
struct Wildcards {
in_port: bool,
dl_vlan: bool,
dl_src: bool,
dl_dst: bool,
dl_type: bool,
nw_proto: bool,
tp_src: bool,
tp_dst: bool,
nw_src: u32,
nw_dst: u32,
dl_vlan_pcp: bool,
nw_tos: bool,
}
impl Wildcards {
fn set_nw_mask(f: u32, offset: usize, v: u32) -> u32 {
let value = (0x3f & v) << offset;
f | value
}
fn get_nw_mask(f: u32, offset: usize) -> u32 {
(f >> offset) & 0x3f
}
fn mask_bits(x: &Option<Mask<u32>>) -> u32 {
match *x {
None => 32,
Some(ref x) => {
match x.mask {
None => 0,
Some(m) => m,
}
}
}
}
fn marshal(w: Wildcards, bytes: &mut Vec<u8>) {
let ret = 0u32;
let ret = bit(0, ret as u64, w.in_port) as u32;
let ret = bit(1, ret as u64, w.dl_vlan) as u32;
let ret = bit(2, ret as u64, w.dl_src) as u32;
let ret = bit(3, ret as u64, w.dl_dst) as u32;
let ret = bit(4, ret as u64, w.dl_type) as u32;
let ret = bit(5, ret as u64, w.nw_proto) as u32;
let ret = bit(6, ret as u64, w.tp_src) as u32;
let ret = bit(7, ret as u64, w.tp_dst) as u32;
let ret = Wildcards::set_nw_mask(ret, 8, w.nw_src);
let ret = Wildcards::set_nw_mask(ret, 14, w.nw_dst);
let ret = bit(20, ret as u64, w.dl_vlan_pcp) as u32;
let ret = bit(21, ret as u64, w.nw_tos) as u32;
bytes.write_u32::<BigEndian>(ret).unwrap()
}
fn parse(bits: u32) -> Wildcards {
Wildcards {
in_port: test_bit(0, bits as u64),
dl_vlan: test_bit(1, bits as u64),
dl_src: test_bit(2, bits as u64),
dl_dst: test_bit(3, bits as u64),
dl_type: test_bit(4, bits as u64),
nw_proto: test_bit(5, bits as u64),
tp_src: test_bit(6, bits as u64),
tp_dst: test_bit(7, bits as u64),
nw_src: Wildcards::get_nw_mask(bits, 8),
nw_dst: Wildcards::get_nw_mask(bits, 14),
dl_vlan_pcp: test_bit(20, bits as u64),
nw_tos: test_bit(21, bits as u64),
}
}
}
impl Pattern {
pub fn match_all() -> Pattern {
Pattern {
dl_src: None,
dl_dst: None,
dl_typ: None,
dl_vlan: None,
dl_vlan_pcp: None,
nw_src: None,
nw_dst: None,
nw_proto: None,
nw_tos: None,
tp_src: None,
tp_dst: None,
in_port: None,
}
}
fn wildcards_of_pattern(m: &Pattern) -> Wildcards {
Wildcards {
in_port: m.in_port.is_none(),
dl_vlan: m.dl_vlan.is_none(),
dl_src: m.dl_src.is_none(),
dl_dst: m.dl_dst.is_none(),
dl_type: m.dl_typ.is_none(),
nw_proto: m.nw_proto.is_none(),
tp_src: m.tp_src.is_none(),
tp_dst: m.tp_dst.is_none(),
nw_src: Wildcards::mask_bits(&m.nw_src),
nw_dst: Wildcards::mask_bits(&m.nw_dst),
dl_vlan_pcp: m.dl_vlan_pcp.is_none(),
nw_tos: m.nw_tos.is_none(),
}
}
fn size_of(_: &Pattern) -> usize {
size_of::<OfpMatch>()
}
fn parse(bytes: &mut Cursor<Vec<u8>>) -> Pattern {
let w = Wildcards::parse(bytes.read_u32::<BigEndian>().unwrap());
let in_port = if w.in_port {
None
} else {
Some(bytes.read_u16::<BigEndian>().unwrap())
};
let dl_src = if w.dl_src {
None
} else {
let mut arr: [u8; 6] = [0; 6];
for i in 0..6 {
arr[i] = bytes.read_u8().unwrap();
}
Some(mac_of_bytes(arr))
};
let dl_dst = if w.dl_dst {
None
} else {
let mut arr: [u8; 6] = [0; 6];
for i in 0..6 {
arr[i] = bytes.read_u8().unwrap();
}
Some(mac_of_bytes(arr))
};
let dl_vlan = if w.dl_vlan {
None
} else {
let vlan = bytes.read_u16::<BigEndian>().unwrap();
if vlan == 0xfff {
Some(None)
} else {
Some(Some(vlan))
}
};
let dl_vlan_pcp = if w.dl_vlan_pcp {
None
} else {
Some(bytes.read_u8().unwrap())
};
bytes.consume(1);
let dl_typ = if w.dl_type {
None
} else {
Some(bytes.read_u16::<BigEndian>().unwrap())
};
let nw_tos = if w.nw_tos {
None
} else {
Some(bytes.read_u8().unwrap())
};
let nw_proto = if w.nw_proto {
None
} else {
Some(bytes.read_u8().unwrap())
};
bytes.consume(2);
let nw_src = if w.nw_src >= 32 {
None
} else if w.nw_src == 0 {
Some(Mask {
value: bytes.read_u32::<BigEndian>().unwrap(),
mask: None,
})
} else {
Some(Mask {
value: bytes.read_u32::<BigEndian>().unwrap(),
mask: Some(w.nw_src),
})
};
let nw_dst = if w.nw_dst >= 32 {
None
} else if w.nw_dst == 0 {
Some(Mask {
value: bytes.read_u32::<BigEndian>().unwrap(),
mask: None,
})
} else {
Some(Mask {
value: bytes.read_u32::<BigEndian>().unwrap(),
mask: Some(w.nw_dst),
})
};
let tp_src = if w.tp_src {
None
} else {
Some(bytes.read_u16::<BigEndian>().unwrap())
};
let tp_dst = if w.tp_dst {
None
} else {
Some(bytes.read_u16::<BigEndian>().unwrap())
};
Pattern {
dl_src: dl_src,
dl_dst: dl_dst,
dl_typ: dl_typ,
dl_vlan: dl_vlan,
dl_vlan_pcp: dl_vlan_pcp,
nw_src: nw_src,
nw_dst: nw_dst,
nw_proto: nw_proto,
nw_tos: nw_tos,
tp_src: tp_src,
tp_dst: tp_dst,
in_port: in_port,
}
}
fn if_word48(n: Option<u64>) -> u64 {
match n {
Some(n) => n,
None => 0,
}
}
fn marshal(p: Pattern, bytes: &mut Vec<u8>) {
let w = Pattern::wildcards_of_pattern(&p);
Wildcards::marshal(w, bytes);
bytes.write_u16::<BigEndian>(p.in_port.unwrap_or(0)).unwrap();
for i in 0..6 {
bytes.write_u8(bytes_of_mac(Self::if_word48(p.dl_src))[i]).unwrap();
}
for i in 0..6 {
bytes.write_u8(bytes_of_mac(Self::if_word48(p.dl_dst))[i]).unwrap();
}
let vlan = match p.dl_vlan {
Some(Some(v)) => v,
Some(None) => 0xffff,
None => 0xffff,
};
bytes.write_u16::<BigEndian>(vlan).unwrap();
bytes.write_u8(p.dl_vlan_pcp.unwrap_or(0)).unwrap();
bytes.write_u8(0).unwrap();
bytes.write_u16::<BigEndian>(p.dl_typ.unwrap_or(0)).unwrap();
bytes.write_u8(p.nw_tos.unwrap_or(0)).unwrap();
bytes.write_u8(p.nw_proto.unwrap_or(0)).unwrap();
bytes.write_u16::<BigEndian>(0).unwrap();
bytes.write_u32::<BigEndian>(p.nw_src
.unwrap_or(Mask {
value: 0,
mask: None,
})
.value)
.unwrap();
bytes.write_u32::<BigEndian>(p.nw_dst
.unwrap_or(Mask {
value: 0,
mask: None,
})
.value)
.unwrap();
bytes.write_u16::<BigEndian>(p.tp_src.unwrap_or(0)).unwrap();
bytes.write_u16::<BigEndian>(p.tp_dst.unwrap_or(0)).unwrap();
}
}
#[repr(packed)]
struct OfpMatch(u32, u16, [u8; 6], [u8; 6], u16, u8, u8, u16, u8, u8, u16, u32, u32, u16, u16);
/// Port behavior.
#[derive(Copy, Clone)]
pub enum PseudoPort {
PhysicalPort(u16),
InPort,
Table,
Normal,
Flood,
AllPorts,
Controller(u64),
Local,
}
#[repr(u16)]
enum OfpPort {
OFPPMax = 0xff00,
OFPPInPort = 0xfff8,
OFPPTable = 0xfff9,
OFPPNormal = 0xfffa,
OFPPFlood = 0xfffb,
OFPPAll = 0xfffc,
OFPPController = 0xfffd,
OFPPLocal = 0xfffe,
OFPPNone = 0xffff,
}
impl PseudoPort {
fn of_int(p: u16) -> Option<PseudoPort> {
if (OfpPort::OFPPNone as u16) == p {
None
} else {
Some(PseudoPort::make(p, 0))
}
}
fn make(p: u16, len: u64) -> PseudoPort {
match p {
p if p == (OfpPort::OFPPInPort as u16) => PseudoPort::InPort,
p if p == (OfpPort::OFPPTable as u16) => PseudoPort::Table,
p if p == (OfpPort::OFPPNormal as u16) => PseudoPort::Normal,
p if p == (OfpPort::OFPPFlood as u16) => PseudoPort::Flood,
p if p == (OfpPort::OFPPAll as u16) => PseudoPort::AllPorts,
p if p == (OfpPort::OFPPController as u16) => PseudoPort::Controller(len),
p if p == (OfpPort::OFPPLocal as u16) => PseudoPort::Local,
_ => {
if p <= (OfpPort::OFPPMax as u16) {
PseudoPort::PhysicalPort(p)
} else {
panic!("Unsupported port number {}", p)
}
}
}
}
fn marshal(pp: PseudoPort, bytes: &mut Vec<u8>) {
match pp {
PseudoPort::PhysicalPort(p) => bytes.write_u16::<BigEndian>(p).unwrap(),
PseudoPort::InPort => bytes.write_u16::<BigEndian>(OfpPort::OFPPInPort as u16).unwrap(),
PseudoPort::Table => bytes.write_u16::<BigEndian>(OfpPort::OFPPTable as u16).unwrap(),
PseudoPort::Normal => bytes.write_u16::<BigEndian>(OfpPort::OFPPNormal as u16).unwrap(),
PseudoPort::Flood => bytes.write_u16::<BigEndian>(OfpPort::OFPPFlood as u16).unwrap(),
PseudoPort::AllPorts => bytes.write_u16::<BigEndian>(OfpPort::OFPPAll as u16).unwrap(),
PseudoPort::Controller(_) => {
bytes.write_u16::<BigEndian>(OfpPort::OFPPController as u16).unwrap()
}
PseudoPort::Local => bytes.write_u16::<BigEndian>(OfpPort::OFPPLocal as u16).unwrap(),
}
}
}
/// Actions associated with flows and packets.
#[derive(Copy, Clone)]
pub enum Action {
Output(PseudoPort),
SetDlVlan(Option<u16>),
SetDlVlanPcp(u8),
SetDlSrc(u64),
SetDlDst(u64),
SetNwSrc(u32),
SetNwDst(u32),
SetNwTos(u8),
SetTpSrc(u16),
SetTpDst(u16),
Enqueue(PseudoPort, u32),
}
#[repr(packed)]
struct OfpActionHeader(u16, u16);
#[repr(packed)]
struct OfpActionOutput(u16, u16);
#[repr(packed)]
struct OfpActionVlanVId(u16, u16);
#[repr(packed)]
struct OfpActionVlanPcp(u8, [u8; 3]);
#[repr(packed)]
struct OfpActionStripVlan(u32);
#[repr(packed)]
struct OfpActionDlAddr([u8; 6], [u8; 6]);
#[repr(packed)]
struct OfpActionNwAddr(u32);
#[repr(packed)]
struct OfpActionTpPort(u16, u16);
#[repr(packed)]
struct OfpActionNwTos(u8, [u8; 3]);
#[repr(packed)]
struct OfpActionEnqueue(u16, [u8; 6], u32);
#[repr(u16)]
enum OfpActionType {
OFPATOutput,
OFPATSetVlanVId,
OFPATSetVlanPCP,
OFPATStripVlan,
OFPATSetDlSrc,
OFPATSetDlDst,
OFPATSetNwSrc,
OFPATSetNwDst,
OFPATSetNwTos,
OFPATSetTpSrc,
OFPATSetTpDst,
OFPATEnqueue,
}
impl Action {
fn type_code(a: &Action) -> OfpActionType {
match *a {
Action::Output(_) => OfpActionType::OFPATOutput,
Action::SetDlVlan(None) => OfpActionType::OFPATStripVlan,
Action::SetDlVlan(Some(_)) => OfpActionType::OFPATSetVlanVId,
Action::SetDlVlanPcp(_) => OfpActionType::OFPATSetVlanPCP,
Action::SetDlSrc(_) => OfpActionType::OFPATSetDlSrc,
Action::SetDlDst(_) => OfpActionType::OFPATSetDlDst,
Action::SetNwSrc(_) => OfpActionType::OFPATSetNwSrc,
Action::SetNwDst(_) => OfpActionType::OFPATSetNwDst,
Action::SetNwTos(_) => OfpActionType::OFPATSetNwTos,
Action::SetTpSrc(_) => OfpActionType::OFPATSetTpSrc,
Action::SetTpDst(_) => OfpActionType::OFPATSetTpDst,
Action::Enqueue(_, _) => OfpActionType::OFPATEnqueue,
}
}
fn size_of(a: &Action) -> usize {
let h = size_of::<OfpActionHeader>();
let body = match *a {
Action::Output(_) => size_of::<OfpActionOutput>(),
Action::SetDlVlan(None) => size_of::<OfpActionStripVlan>(),
Action::SetDlVlan(Some(_)) => size_of::<OfpActionVlanVId>(),
Action::SetDlVlanPcp(_) => size_of::<OfpActionVlanPcp>(),
Action::SetDlSrc(_) |
Action::SetDlDst(_) => size_of::<OfpActionDlAddr>(),
Action::SetNwSrc(_) |
Action::SetNwDst(_) => size_of::<OfpActionNwAddr>(),
Action::SetNwTos(_) => size_of::<OfpActionNwTos>(),
Action::SetTpSrc(_) |
Action::SetTpDst(_) => size_of::<OfpActionTpPort>(),
Action::Enqueue(_, _) => size_of::<OfpActionEnqueue>(),
};
h + body
}
fn size_of_sequence(actions: &Vec<Action>) -> usize {
actions.iter().fold(0, |acc, x| Action::size_of(x) + acc)
}
fn _parse(bytes: &mut Cursor<Vec<u8>>) -> Action {
let action_code = bytes.read_u16::<BigEndian>().unwrap();
let _ = bytes.read_u16::<BigEndian>().unwrap();
let action = match action_code {
t if t == (OfpActionType::OFPATOutput as u16) => {
let port_code = bytes.read_u16::<BigEndian>().unwrap();
let len = bytes.read_u16::<BigEndian>().unwrap();
Action::Output(PseudoPort::make(port_code, len as u64))
}
t if t == (OfpActionType::OFPATSetVlanVId as u16) => {
let vid = bytes.read_u16::<BigEndian>().unwrap();
bytes.consume(2);
if vid == 0xffff {
Action::SetDlVlan(None)
} else {
Action::SetDlVlan(Some(vid))
}
}
t if t == (OfpActionType::OFPATSetVlanPCP as u16) => {
let pcp = bytes.read_u8().unwrap();
bytes.consume(3);
Action::SetDlVlanPcp(pcp)
}
t if t == (OfpActionType::OFPATStripVlan as u16) => {
bytes.consume(4);
Action::SetDlVlan(None)
}
t if t == (OfpActionType::OFPATSetDlSrc as u16) => {
let mut dl_addr: [u8; 6] = [0; 6];
for i in 0..6 {
dl_addr[i] = bytes.read_u8().unwrap();
}
bytes.consume(6);
Action::SetDlSrc(mac_of_bytes(dl_addr))
}
t if t == (OfpActionType::OFPATSetDlDst as u16) => {
let mut dl_addr: [u8; 6] = [0; 6];
for i in 0..6 {
dl_addr[i] = bytes.read_u8().unwrap();
}
bytes.consume(6);
Action::SetDlDst(mac_of_bytes(dl_addr))
}
t if t == (OfpActionType::OFPATSetNwSrc as u16) => {
Action::SetNwSrc(bytes.read_u32::<BigEndian>().unwrap())
}
t if t == (OfpActionType::OFPATSetNwDst as u16) => {
Action::SetNwDst(bytes.read_u32::<BigEndian>().unwrap())
}
t if t == (OfpActionType::OFPATSetNwTos as u16) => {
let nw_tos = bytes.read_u8().unwrap();
bytes.consume(3);
Action::SetNwTos(nw_tos)
}
t if t == (OfpActionType::OFPATSetTpSrc as u16) => {
let pt = bytes.read_u16::<BigEndian>().unwrap();
bytes.consume(2);
Action::SetTpSrc(pt)
}
t if t == (OfpActionType::OFPATSetTpDst as u16) => {
let pt = bytes.read_u16::<BigEndian>().unwrap();
bytes.consume(2);
Action::SetTpDst(pt)
}
t if t == (OfpActionType::OFPATEnqueue as u16) => {
let pt = bytes.read_u16::<BigEndian>().unwrap();
bytes.consume(6);
let qid = bytes.read_u32::<BigEndian>().unwrap();
Action::Enqueue(PseudoPort::make(pt, 0), qid)
}
t => panic!("Unrecognized OfpActionType {}", t),
};
action
}
fn parse_sequence(bytes: &mut Cursor<Vec<u8>>) -> Vec<Action> {
if bytes.get_ref().is_empty() {
vec![]
} else {
let action = Action::_parse(bytes);
let mut v = vec![action];
v.append(&mut Action::parse_sequence(bytes));
v
}
}
fn move_controller_last(acts: Vec<Action>) -> Vec<Action> {
let (mut to_ctrl, mut not_to_ctrl): (Vec<Action>, Vec<Action>) = acts.into_iter()
.partition(|act| match *act {
Action::Output(PseudoPort::Controller(_)) => true,
_ => false,
});
not_to_ctrl.append(&mut to_ctrl);
not_to_ctrl
}
fn marshal(act: Action, bytes: &mut Vec<u8>) {
bytes.write_u16::<BigEndian>(Action::type_code(&act) as u16).unwrap();
bytes.write_u16::<BigEndian>(Action::size_of(&act) as u16).unwrap();
match act {
Action::Output(pp) => {
PseudoPort::marshal(pp, bytes);
bytes.write_u16::<BigEndian>(match pp {
PseudoPort::Controller(w) => w as u16,
_ => 0,
})
.unwrap()
}
Action::SetDlVlan(None) => bytes.write_u32::<BigEndian>(0xffff).unwrap(),
Action::SetDlVlan(Some(vid)) => {
bytes.write_u16::<BigEndian>(vid).unwrap();
bytes.write_u16::<BigEndian>(0).unwrap();
}
Action::SetDlVlanPcp(n) => {
bytes.write_u8(n).unwrap();
for _ in 0..3 {
bytes.write_u8(0).unwrap();
}
}
Action::SetDlSrc(mac) |
Action::SetDlDst(mac) => {
let mac = bytes_of_mac(mac);
for i in 0..6 {
bytes.write_u8(mac[i]).unwrap();
}
for _ in 0..6 {
bytes.write_u8(0).unwrap();
}
}
Action::SetNwSrc(addr) |
Action::SetNwDst(addr) => bytes.write_u32::<BigEndian>(addr).unwrap(),
Action::SetNwTos(n) => {
bytes.write_u8(n).unwrap();
for _ in 0..3 {
bytes.write_u8(0).unwrap();
}
}
Action::SetTpSrc(pt) |
Action::SetTpDst(pt) => {
bytes.write_u16::<BigEndian>(pt).unwrap();
bytes.write_u16::<BigEndian>(0).unwrap();
}
Action::Enqueue(pp, qid) => {
PseudoPort::marshal(pp, bytes);
for _ in 0..6 {
bytes.write_u8(0).unwrap();
}
bytes.write_u32::<BigEndian>(qid).unwrap();
}
}
}
}
/// How long before a flow entry expires.
pub enum Timeout {
Permanent,
ExpiresAfter(u16),
}
impl Timeout {
fn of_int(tm: u16) -> Timeout {
match tm {
0 => Timeout::Permanent,
d => Timeout::ExpiresAfter(d),
}
}
fn to_int(tm: Timeout) -> u16 {
match tm {
Timeout::Permanent => 0,
Timeout::ExpiresAfter(d) => d,
}
}
}
/// Capabilities supported by the datapath.
pub struct Capabilities {
pub flow_stats: bool,
pub table_stats: bool,
pub port_stats: bool,
pub stp: bool,
pub ip_reasm: bool,
pub queue_stats: bool,
pub arp_match_ip: bool,
}
/// Actions supported by the datapath.
pub struct SupportedActions {
pub output: bool,
pub set_vlan_id: bool,
pub set_vlan_pcp: bool,
pub strip_vlan: bool,
pub set_dl_src: bool,
pub set_dl_dst: bool,
pub set_nw_src: bool,
pub set_nw_dst: bool,
pub set_nw_tos: bool,
pub set_tp_src: bool,
pub set_tp_dst: bool,
pub enqueue: bool,
pub vendor: bool,
}
/// Switch features.
pub struct SwitchFeatures {
pub datapath_id: u64,
pub num_buffers: u32,
pub num_tables: u8,
pub supported_capabilities: Capabilities,
pub supported_actions: SupportedActions,
pub ports: Vec<PortDesc>,
}
#[repr(packed)]
struct OfpSwitchFeatures(u64, u32, u8, [u8; 3], u32, u32);
impl MessageType for SwitchFeatures {
fn size_of(sf: &SwitchFeatures) -> usize {
let pds: usize = sf.ports.iter().map(|pd| PortDesc::size_of(pd)).sum();
size_of::<OfpSwitchFeatures>() + pds
}
fn parse(buf: &[u8]) -> SwitchFeatures {
let mut bytes = Cursor::new(buf.to_vec());
let datapath_id = bytes.read_u64::<BigEndian>().unwrap();
let num_buffers = bytes.read_u32::<BigEndian>().unwrap();
let num_tables = bytes.read_u8().unwrap();
bytes.consume(3);
let supported_capabilities = {
let d = bytes.read_u32::<BigEndian>().unwrap();
Capabilities {
flow_stats: test_bit(0, d as u64),
table_stats: test_bit(1, d as u64),
port_stats: test_bit(2, d as u64),
stp: test_bit(3, d as u64),
ip_reasm: test_bit(5, d as u64),
queue_stats: test_bit(6, d as u64),
arp_match_ip: test_bit(7, d as u64),
}
};
let supported_actions = {
let d = bytes.read_u32::<BigEndian>().unwrap();
SupportedActions {
output: test_bit(0, d as u64),
set_vlan_id: test_bit(1, d as u64),
set_vlan_pcp: test_bit(2, d as u64),
strip_vlan: test_bit(3, d as u64),
set_dl_src: test_bit(4, d as u64),
set_dl_dst: test_bit(5, d as u64),
set_nw_src: test_bit(6, d as u64),
set_nw_dst: test_bit(7, d as u64),
set_nw_tos: test_bit(8, d as u64),
set_tp_src: test_bit(9, d as u64),
set_tp_dst: test_bit(10, d as u64),
enqueue: test_bit(11, d as u64),
vendor: test_bit(12, d as u64),
}
};
let ports = {
let mut v = vec![];
let pos = bytes.position() as usize;
let rem = bytes.get_ref()[pos..].to_vec();
let num_ports = rem.len() / size_of::<OfpPhyPort>();
for _ in 0..num_ports {
v.push(PortDesc::parse(&mut bytes))
}
v
};
SwitchFeatures {
datapath_id: datapath_id,
num_buffers: num_buffers,
num_tables: num_tables,
supported_capabilities: supported_capabilities,
supported_actions: supported_actions,
ports: ports,
}
}
fn marshal(_: SwitchFeatures, _: &mut Vec<u8>) {}
}
/// Type of modification to perform on a flow table.
#[repr(u16)]
pub enum FlowModCmd {
AddFlow,
ModFlow,
ModStrictFlow,
DeleteFlow,
DeleteStrictFlow,
}
/// Represents modifications to a flow table from the controller.
pub struct FlowMod {
pub command: FlowModCmd,
pub pattern: Pattern,
pub priority: u16,
pub actions: Vec<Action>,
pub cookie: u64,
pub idle_timeout: Timeout,
pub hard_timeout: Timeout,
pub notify_when_removed: bool,
pub apply_to_packet: Option<u32>,
pub out_port: Option<PseudoPort>,
pub check_overlap: bool,
}
#[repr(packed)]
struct OfpFlowMod(u64, u16, u16, u16, u16, u32, u16, u16);
impl FlowMod {
fn flags_to_int(check_overlap: bool, notify_when_removed: bool) -> u16 {
(if check_overlap { 1 << 1 } else { 0 }) | (if notify_when_removed { 1 << 0 } else { 0 })
}
fn check_overlap_of_flags(flags: u16) -> bool {
2 & flags != 0
}
fn notify_when_removed_of_flags(flags: u16) -> bool {
1 & flags != 0
}
}
impl MessageType for FlowMod {
fn size_of(msg: &FlowMod) -> usize {
Pattern::size_of(&msg.pattern) + size_of::<OfpFlowMod>() +
Action::size_of_sequence(&msg.actions)
}
fn parse(buf: &[u8]) -> FlowMod {
let mut bytes = Cursor::new(buf.to_vec());
let pattern = Pattern::parse(&mut bytes);
let cookie = bytes.read_u64::<BigEndian>().unwrap();
let command = unsafe { transmute(bytes.read_u16::<BigEndian>().unwrap()) };
let idle = Timeout::of_int(bytes.read_u16::<BigEndian>().unwrap());
let hard = Timeout::of_int(bytes.read_u16::<BigEndian>().unwrap());
let prio = bytes.read_u16::<BigEndian>().unwrap();
let buffer_id = bytes.read_i32::<BigEndian>().unwrap();
let out_port = PseudoPort::of_int(bytes.read_u16::<BigEndian>().unwrap());
let flags = bytes.read_u16::<BigEndian>().unwrap();
let actions = Action::parse_sequence(&mut bytes);
FlowMod {
command: command,
pattern: pattern,
priority: prio,
actions: actions,
cookie: cookie,
idle_timeout: idle,
hard_timeout: hard,
notify_when_removed: FlowMod::notify_when_removed_of_flags(flags),
apply_to_packet: {
match buffer_id {
-1 => None,
n => Some(n as u32),
}
},
out_port: out_port,
check_overlap: FlowMod::check_overlap_of_flags(flags),
}
}
fn marshal(fm: FlowMod, bytes: &mut Vec<u8>) {
Pattern::marshal(fm.pattern, bytes);
bytes.write_u64::<BigEndian>(fm.cookie).unwrap();
bytes.write_u16::<BigEndian>(fm.command as u16).unwrap();
bytes.write_u16::<BigEndian>(Timeout::to_int(fm.idle_timeout)).unwrap();
bytes.write_u16::<BigEndian>(Timeout::to_int(fm.hard_timeout)).unwrap();
bytes.write_u16::<BigEndian>(fm.priority).unwrap();
bytes.write_i32::<BigEndian>(match fm.apply_to_packet {
None => -1,
Some(buf_id) => buf_id as i32,
})
.unwrap();
match fm.out_port {
None => bytes.write_u16::<BigEndian>(OfpPort::OFPPNone as u16).unwrap(),
Some(x) => PseudoPort::marshal(x, bytes),
}
bytes.write_u16::<BigEndian>(FlowMod::flags_to_int(fm.check_overlap,
fm.notify_when_removed))
.unwrap();
for act in Action::move_controller_last(fm.actions) {
match act {
Action::Output(PseudoPort::Table) => {
panic!("OFPPTable not allowed in installed flow.")
}
_ => (),
}
Action::marshal(act, bytes)
}
}
}
/// The data associated with a packet received by the controller.
#[derive(Debug)]
pub enum Payload {
Buffered(u32, Vec<u8>),
NotBuffered(Vec<u8>),
}
impl Payload {
pub fn size_of(payload: &Payload) -> usize {
match *payload {
Payload::Buffered(_, ref buf) |
Payload::NotBuffered(ref buf) => buf.len(),
}
}
fn marshal(payload: Payload, bytes: &mut Vec<u8>) {
match payload {
Payload::Buffered(_, buf) |
Payload::NotBuffered(buf) => bytes.write_all(&buf).unwrap(),
}
}
}
/// The reason a packet arrives at the controller.
#[repr(u8)]
#[derive(Debug)]
pub enum PacketInReason {
NoMatch,
ExplicitSend,
}
/// Represents packets received by the datapath and sent to the controller.
#[derive(Debug)]
pub struct PacketIn {
pub input_payload: Payload,
pub total_len: u16,
pub port: u16,
pub reason: PacketInReason,
}
#[repr(packed)]
struct OfpPacketIn(i32, u16, u16, u8, u8);
impl MessageType for PacketIn {
fn size_of(pi: &PacketIn) -> usize {
size_of::<OfpPacketIn>() + Payload::size_of(&pi.input_payload)
}
fn parse(buf: &[u8]) -> PacketIn {
let mut bytes = Cursor::new(buf.to_vec());
let buf_id = match bytes.read_i32::<BigEndian>().unwrap() {
-1 => None,
n => Some(n),
};
let total_len = bytes.read_u16::<BigEndian>().unwrap();
let port = bytes.read_u16::<BigEndian>().unwrap();
let reason = unsafe { transmute(bytes.read_u8().unwrap()) };
bytes.consume(1);
let pk = bytes.fill_buf().unwrap().to_vec();
let payload = match buf_id {
None => Payload::NotBuffered(pk),
Some(n) => Payload::Buffered(n as u32, pk),
};
println!("=========== packet in =================");
println!("payload: {:?}", payload);
println!("total_len: {:?}", total_len);
println!("port: {:?}", port);
println!("reason: {:?}", reason);
println!("=======================================");
PacketIn {
input_payload: payload,
total_len: total_len,
port: port,
reason: reason,
}
}
fn marshal(pi: PacketIn, bytes: &mut Vec<u8>) {
let buf_id = match pi.input_payload {
Payload::NotBuffered(_) => -1,
Payload::Buffered(n, _) => n as i32,
};
bytes.write_i32::<BigEndian>(buf_id).unwrap();
bytes.write_u16::<BigEndian>(pi.total_len).unwrap();
bytes.write_u16::<BigEndian>(pi.port).unwrap();
bytes.write_u8(pi.reason as u8).unwrap();
Payload::marshal(pi.input_payload, bytes)
}
}
/// Represents packets sent from the controller.
pub struct PacketOut {
pub output_payload: Payload,
pub port_id: Option<u16>,
pub apply_actions: Vec<Action>,
}
#[repr(packed)]
struct OfpPacketOut(u32, u16, u16);
impl MessageType for PacketOut {
fn size_of(po: &PacketOut) -> usize {
size_of::<OfpPacketOut>() + Action::size_of_sequence(&po.apply_actions) +
Payload::size_of(&po.output_payload)
}
fn parse(buf: &[u8]) -> PacketOut {
let mut bytes = Cursor::new(buf.to_vec());
let buf_id = match bytes.read_i32::<BigEndian>().unwrap() {
-1 => None,
n => Some(n),
};
let in_port = bytes.read_u16::<BigEndian>().unwrap();
let actions_len = bytes.read_u16::<BigEndian>().unwrap();
let mut actions_buf = vec![0; actions_len as usize];
bytes.read_exact(&mut actions_buf).unwrap();
let mut actions_bytes = Cursor::new(actions_buf);
let actions = Action::parse_sequence(&mut actions_bytes);
PacketOut {
output_payload: match buf_id {
None => Payload::NotBuffered(bytes.fill_buf().unwrap().to_vec()),
Some(n) => Payload::Buffered(n as u32, bytes.fill_buf().unwrap().to_vec()),
},
port_id: {
if in_port == OfpPort::OFPPNone as u16 {
None
} else {
Some(in_port)
}
},
apply_actions: actions,
}
}
fn marshal(po: PacketOut, bytes: &mut Vec<u8>) {
// buf_id
bytes.write_i32::<BigEndian>(match po.output_payload {
Payload::Buffered(n, _) => n as i32,
Payload::NotBuffered(_) => -1,
})
.unwrap();
match po.port_id {
Some(id) => PseudoPort::marshal(PseudoPort::PhysicalPort(id), bytes),
None => bytes.write_u16::<BigEndian>(OfpPort::OFPPNone as u16).unwrap(),
}
bytes.write_u16::<BigEndian>(Action::size_of_sequence(&po.apply_actions) as u16).unwrap();
for act in Action::move_controller_last(po.apply_actions) {
Action::marshal(act, bytes);
}
Payload::marshal(po.output_payload, bytes)
}
}
/// Reason a flow was removed from a switch
#[repr(u8)]
pub enum FlowRemovedReason {
IdleTimeout,
HardTimeout,
Delete,
}
/// Flow removed (datapath -> controller)
pub struct FlowRemoved {
pub pattern: Pattern,
pub cookie: i64,
pub priority: u16,
pub reason: FlowRemovedReason,
pub duration_sec: u32,
pub duration_nsec: u32,
pub idle_timeout: Timeout,
pub packet_count: u64,
pub byte_count: u64,
}
#[repr(packed)]
struct OfpFlowRemoved(u64, u16, u8, u8, u32, u32, u16, u16, u64, u64);
impl MessageType for FlowRemoved {
fn size_of(f: &FlowRemoved) -> usize {
Pattern::size_of(&f.pattern) + size_of::<OfpFlowRemoved>()
}
fn parse(buf: &[u8]) -> FlowRemoved {
let mut bytes = Cursor::new(buf.to_vec());
let pattern = Pattern::parse(&mut bytes);
let cookie = bytes.read_i64::<BigEndian>().unwrap();
let priority = bytes.read_u16::<BigEndian>().unwrap();
let reason = unsafe { transmute(bytes.read_u8().unwrap()) };
bytes.consume(1);
let duration_sec = bytes.read_u32::<BigEndian>().unwrap();
let duration_nsec = bytes.read_u32::<BigEndian>().unwrap();
let idle = Timeout::of_int(bytes.read_u16::<BigEndian>().unwrap());
bytes.consume(2);
let packet_count = bytes.read_u64::<BigEndian>().unwrap();
let byte_count = bytes.read_u64::<BigEndian>().unwrap();
FlowRemoved {
pattern: pattern,
cookie: cookie,
priority: priority,
reason: reason,
duration_sec: duration_sec,
duration_nsec: duration_nsec,
idle_timeout: idle,
packet_count: packet_count,
byte_count: byte_count,
}
}
fn marshal(f: FlowRemoved, bytes: &mut Vec<u8>) {
Pattern::marshal(f.pattern, bytes);
bytes.write_i64::<BigEndian>(f.cookie).unwrap();
bytes.write_u16::<BigEndian>(f.priority).unwrap();
bytes.write_u8(f.reason as u8).unwrap();
bytes.write_u8(0).unwrap();
bytes.write_u32::<BigEndian>(f.duration_sec).unwrap();
bytes.write_u32::<BigEndian>(f.duration_nsec).unwrap();
bytes.write_u16::<BigEndian>(Timeout::to_int(f.idle_timeout)).unwrap();
bytes.write_u64::<BigEndian>(f.packet_count).unwrap();
bytes.write_u64::<BigEndian>(f.byte_count).unwrap();
}
}
/// STP state of a port.
#[repr(u8)]
pub enum StpState {
Listen,
Learn,
Forward,
Block,
}
/// Current state of a physical port. Not configurable by the controller.
pub struct PortState {
pub down: bool,
pub stp_state: StpState,
}
/// Features of physical ports available in a datapath.
pub struct PortFeatures {
pub f_10mbhd: bool,
pub f_10mbfd: bool,
pub f_100mbhd: bool,
pub f_100mbfd: bool,
pub f_1gbhd: bool,
pub f_1gbfd: bool,
pub f_10gbfd: bool,
pub copper: bool,
pub fiber: bool,
pub autoneg: bool,
pub pause: bool,
pub pause_asym: bool,
}
impl PortFeatures {
fn of_int(d: u32) -> PortFeatures {
PortFeatures {
f_10mbhd: test_bit(0, d as u64),
f_10mbfd: test_bit(1, d as u64),
f_100mbhd: test_bit(2, d as u64),
f_100mbfd: test_bit(3, d as u64),
f_1gbhd: test_bit(4, d as u64),
f_1gbfd: test_bit(5, d as u64),
f_10gbfd: test_bit(6, d as u64),
copper: test_bit(7, d as u64),
fiber: test_bit(8, d as u64),
autoneg: test_bit(9, d as u64),
pause: test_bit(10, d as u64),
pause_asym: test_bit(11, d as u64),
}
}
}
/// Flags to indicate behavior of the physical port.
///
/// These flags are used both to describe the current configuration of a physical port,
/// and to configure a port's behavior.
pub struct PortConfig {
pub down: bool,
pub no_stp: bool,
pub no_recv: bool,
pub no_recv_stp: bool,
pub no_flood: bool,
pub no_fwd: bool,
pub no_packet_in: bool,
}
/// Description of a physical port.
pub struct PortDesc {
pub port_no: u16,
pub hw_addr: u64,
pub name: String,
pub config: PortConfig,
pub state: PortState,
pub curr: PortFeatures,
pub advertised: PortFeatures,
pub supported: PortFeatures,
pub peer: PortFeatures,
}
#[repr(packed)]
struct OfpPhyPort(u16, [u8; 6], [u8; 16], u32, u32, u32, u32, u32, u32);
impl PortDesc {
fn size_of(_: &PortDesc) -> usize {
size_of::<OfpPhyPort>()
}
fn parse(bytes: &mut Cursor<Vec<u8>>) -> PortDesc {
let port_no = bytes.read_u16::<BigEndian>().unwrap();
let hw_addr = {
let mut arr: [u8; 6] = [0; 6];
for i in 0..6 {
arr[i] = bytes.read_u8().unwrap();
}
mac_of_bytes(arr)
};
let name = {
let mut arr: [u8; 16] = [0; 16];
for i in 0..16 {
arr[i] = bytes.read_u8().unwrap();
}
String::from_utf8(arr.to_vec()).unwrap()
};
let config = {
let d = bytes.read_u32::<BigEndian>().unwrap();
PortConfig {
down: test_bit(0, d as u64),
no_stp: test_bit(1, d as u64),
no_recv: test_bit(2, d as u64),
no_recv_stp: test_bit(3, d as u64),
no_flood: test_bit(4, d as u64),
no_fwd: test_bit(5, d as u64),
no_packet_in: test_bit(6, d as u64),
}
};
let state = {
let d = bytes.read_u32::<BigEndian>().unwrap();
PortState {
down: test_bit(0, d as u64),
stp_state: {
let mask: u32 = 3 << 8;
let d_masked = d & mask;
if d_masked == (StpState::Listen as u32) << 8 {
StpState::Listen
} else if d_masked == (StpState::Learn as u32) << 8 {
StpState::Learn
} else if d_masked == (StpState::Forward as u32) << 8 {
StpState::Forward
} else if d_masked == (StpState::Block as u32) << 8 {
StpState::Block
} else {
panic!("Unexpected ofp_port_state for STP: {}", d_masked)
}
},
}
};
let curr = PortFeatures::of_int(bytes.read_u32::<BigEndian>().unwrap());
let advertised = PortFeatures::of_int(bytes.read_u32::<BigEndian>().unwrap());
let supported = PortFeatures::of_int(bytes.read_u32::<BigEndian>().unwrap());
let peer = PortFeatures::of_int(bytes.read_u32::<BigEndian>().unwrap());
PortDesc {
port_no: port_no,
hw_addr: hw_addr,
name: name,
config: config,
state: state,
curr: curr,
advertised: advertised,
supported: supported,
peer: peer,
}
}
}
/// What changed about a physical port.
#[repr(u8)]
pub enum PortReason {
PortAdd,
PortDelete,
PortModify,
}
/// A physical port has changed in the datapath.
pub struct PortStatus {
pub reason: PortReason,
pub desc: PortDesc,
}
impl MessageType for PortStatus {
fn size_of(_: &PortStatus) -> usize {
size_of::<PortReason>() + size_of::<OfpPhyPort>()
}
fn parse(buf: &[u8]) -> PortStatus {
let mut bytes = Cursor::new(buf.to_vec());
let reason = unsafe { transmute(bytes.read_u8().unwrap()) };
bytes.consume(7);
let desc = PortDesc::parse(&mut bytes);
PortStatus {
reason: reason,
desc: desc,
}
}
fn marshal(_: PortStatus, _: &mut Vec<u8>) {}
}
/// Reason Hello failed.
#[repr(u16)]
#[derive(Debug)]
pub enum HelloFailed {
Incompatible,
EPerm,
}
/// Reason the controller made a bad request to a switch.
#[repr(u16)]
#[derive(Debug)]
pub enum BadRequest {
BadVersion,
BadType,
BadStat,
BadVendor,
BadSubType,
EPerm,
BadLen,
BufferEmpty,
BufferUnknown,
}
/// Reason the controller action failed.
#[repr(u16)]
#[derive(Debug)]
pub enum BadAction {
BadType,
BadLen,
BadVendor,
BadVendorType,
BadOutPort,
BadArgument,
EPerm,
TooMany,
BadQueue,
}
/// Reason a FlowMod from the controller failed.
#[repr(u16)]
#[derive(Debug)]
pub enum FlowModFailed {
AllTablesFull,
Overlap,
EPerm,
BadEmergTimeout,
BadCommand,
Unsupported,
}
/// Reason a PortMod from the controller failed.
#[repr(u16)]
#[derive(Debug)]
pub enum PortModFailed {
BadPort,
BadHwAddr,
}
/// Reason a queue operation from the controller failed.
#[repr(u16)]
#[derive(Debug)]
pub enum QueueOpFailed {
BadPort,
BadQueue,
EPerm,
}
/// High-level type of OpenFlow error
#[derive(Debug)]
pub enum ErrorType {
HelloFailed(HelloFailed),
BadRequest(BadRequest),
BadAction(BadAction),
FlowModFailed(FlowModFailed),
PortModFailed(PortModFailed),
QueueOpFailed(QueueOpFailed),
}
/// Error message (datapath -> controller)
#[derive(Debug)]
pub enum Error {
Error(ErrorType, Vec<u8>),
}
#[repr(packed)]
struct OfpErrorMsg(u16, u16);
impl MessageType for Error {
fn size_of(err: &Error) -> usize {
match *err {
Error::Error(_, ref body) => size_of::<OfpErrorMsg>() + body.len(),
}
}
fn parse(buf: &[u8]) -> Error {
let mut bytes = Cursor::new(buf.to_vec());
let error_type = bytes.read_u16::<BigEndian>().unwrap();
let error_code = bytes.read_u16::<BigEndian>().unwrap();
let code = match error_type {
0 => ErrorType::HelloFailed(unsafe { transmute(error_code) }),
1 => ErrorType::BadRequest(unsafe { transmute(error_code) }),
2 => ErrorType::BadAction(unsafe { transmute(error_code) }),
3 => ErrorType::FlowModFailed(unsafe { transmute(error_code) }),
4 => ErrorType::PortModFailed(unsafe { transmute(error_code) }),
5 => ErrorType::QueueOpFailed(unsafe { transmute(error_code) }),
_ => panic!("bad ErrorType in Error {}", error_type),
};
Error::Error(code, bytes.fill_buf().unwrap().to_vec())
}
fn marshal(_: Error, _: &mut Vec<u8>) {}
}
/// Encapsulates handling of messages implementing `MessageType` trait.
pub mod message {
use super::*;
use std::io::Write;
use ofp_header::OfpHeader;
use ofp_message::OfpMessage;
use packet::Packet;
/// Abstractions of OpenFlow 1.0 messages mapping to message codes.
pub enum Message {
Hello,
Error(Error),
EchoRequest(Vec<u8>),
EchoReply(Vec<u8>),
FeaturesReq,
FeaturesReply(SwitchFeatures),
FlowMod(FlowMod),
PacketIn(PacketIn),
FlowRemoved(FlowRemoved),
PortStatus(PortStatus),
PacketOut(PacketOut),
BarrierRequest,
BarrierReply,
}
impl Message {
/// Map `Message` to associated OpenFlow message type code `MsgCode`.
fn msg_code_of_message(msg: &Message) -> MsgCode {
match *msg {
Message::Hello => MsgCode::Hello,
Message::Error(_) => MsgCode::Error,
Message::EchoRequest(_) => MsgCode::EchoReq,
Message::EchoReply(_) => MsgCode::EchoResp,
Message::FeaturesReq => MsgCode::FeaturesReq,
Message::FeaturesReply(_) => MsgCode::FeaturesResp,
Message::FlowMod(_) => MsgCode::FlowMod,
Message::PacketIn(_) => MsgCode::PacketIn,
Message::FlowRemoved(_) => MsgCode::FlowRemoved,
Message::PortStatus(_) => MsgCode::PortStatus,
Message::PacketOut(_) => MsgCode::PacketOut,
Message::BarrierRequest => MsgCode::BarrierReq,
Message::BarrierReply => MsgCode::BarrierResp,
}
}
/// Marshal the OpenFlow message `msg`.
fn marshal_body(msg: Message, bytes: &mut Vec<u8>) {
match msg {
Message::Hello => (),
Message::Error(buf) => Error::marshal(buf, bytes),
Message::EchoReply(buf) => bytes.write_all(&buf).unwrap(),
Message::EchoRequest(buf) => bytes.write_all(&buf).unwrap(),
Message::FeaturesReq => (),
Message::FlowMod(flow_mod) => FlowMod::marshal(flow_mod, bytes),
Message::PacketIn(packet_in) => PacketIn::marshal(packet_in, bytes),
Message::FlowRemoved(flow) => FlowRemoved::marshal(flow, bytes),
Message::PortStatus(sts) => PortStatus::marshal(sts, bytes),
Message::PacketOut(po) => PacketOut::marshal(po, bytes),
Message::BarrierRequest | Message::BarrierReply => (),
_ => (),
}
}
}
impl OfpMessage for Message {
fn size_of(msg: &Message) -> usize {
match *msg {
Message::Hello => OfpHeader::size(),
Message::Error(ref err) => Error::size_of(err),
Message::EchoRequest(ref buf) => OfpHeader::size() + buf.len(),
Message::EchoReply(ref buf) => OfpHeader::size() + buf.len(),
Message::FeaturesReq => OfpHeader::size(),
Message::FlowMod(ref flow_mod) => OfpHeader::size() + FlowMod::size_of(flow_mod),
Message::PacketIn(ref packet_in) => {
OfpHeader::size() + PacketIn::size_of(packet_in)
}
Message::FlowRemoved(ref flow) => OfpHeader::size() + FlowRemoved::size_of(flow),
Message::PortStatus(ref ps) => OfpHeader::size() + PortStatus::size_of(ps),
Message::PacketOut(ref po) => OfpHeader::size() + PacketOut::size_of(po),
Message::BarrierRequest | Message::BarrierReply => OfpHeader::size(),
_ => 0,
}
}
fn header_of(xid: u32, msg: &Message) -> OfpHeader {
let sizeof_buf = Self::size_of(&msg);
OfpHeader::new(0x01,
Self::msg_code_of_message(msg) as u8,
sizeof_buf as u16,
xid)
}
fn marshal(xid: u32, msg: Message) -> Vec<u8> {
// ประกอบ Openflow Header
let hdr = Self::header_of(xid, &msg);
let mut bytes = vec![];
// นำ header ใส่เข้าไปใน vec
OfpHeader::marshal(&mut bytes, hdr);
Message::marshal_body(msg, &mut bytes);
bytes
}
fn parse(header: &OfpHeader, buf: &[u8]) -> (u32, Message) {
let typ = header.type_code();
let msg = match typ {
MsgCode::Hello => {
println!("Hello!");
Message::Hello
}
MsgCode::Error => {
println!("Error");
Message::Error(Error::parse(buf))
}
MsgCode::EchoReq => Message::EchoRequest(buf.to_vec()),
MsgCode::EchoResp => Message::EchoReply(buf.to_vec()),
MsgCode::FeaturesResp => {
println!("FeaturesResp");
Message::FeaturesReply(SwitchFeatures::parse(buf))
}
MsgCode::FlowMod => {
println!("FlowMod");
Message::FlowMod(FlowMod::parse(buf))
}
MsgCode::PacketIn => {
println!("PacketIn");
Message::PacketIn(PacketIn::parse(buf))
}
MsgCode::FlowRemoved => {
println!("FlowRemoved");
Message::FlowRemoved(FlowRemoved::parse(buf))
}
MsgCode::PortStatus => {
println!("PortStatus");
Message::PortStatus(PortStatus::parse(buf))
}
MsgCode::PacketOut => {
println!("PacketOut");
Message::PacketOut(PacketOut::parse(buf))
}
MsgCode::BarrierReq => Message::BarrierRequest,
MsgCode::BarrierResp => Message::BarrierReply,
code => panic!("Unexpected message type {:?}", code),
};
(header.xid(), msg)
}
}
/// Return a `FlowMod` adding a flow parameterized by the given `priority`, `pattern`,
/// and `actions`.
pub fn add_flow(prio: u16, pattern: Pattern, actions: Vec<Action>) -> FlowMod {
FlowMod {
command: FlowModCmd::AddFlow,
pattern: pattern,
priority: prio,
actions: actions,
cookie: 0,
idle_timeout: Timeout::Permanent,
hard_timeout: Timeout::Permanent,
notify_when_removed: false,
out_port: None,
apply_to_packet: None,
check_overlap: false,
}
}
/// Parse a payload buffer into a network level packet.
pub fn parse_payload(p: &Payload) -> Packet {
match *p {
Payload::Buffered(_, ref b) |
Payload::NotBuffered(ref b) => Packet::parse(&b),
}
}
}
use std::io::{BufRead, Cursor, Read};
use std::mem::size_of;
use byteorder::{BigEndian, ReadBytesExt};
use bits::test_bit;
pub fn bytes_of_mac(addr: u64) -> [u8; 6] {
let mut arr = [0; 6];
for i in 0..6 {
arr[i] = ((addr >> (8 * i)) & 0xff) as u8;
}
arr
}
pub fn mac_of_bytes(addr: [u8; 6]) -> u64 {
fn byte(u: &[u8; 6], i: usize) -> u64 {
u[i] as u64
};
(byte(&addr, 0) << 8 * 5) | (byte(&addr, 1) << 8 * 4) | (byte(&addr, 2) << 8 * 3) |
(byte(&addr, 3) << 8 * 2) | (byte(&addr, 4) << 8 * 1) | (byte(&addr, 5))
}
/// TCP Header flags.
#[derive(Debug)]
pub struct TcpFlags {
/// ECN-nonce concealment protection.
pub ns: bool,
/// Congestion window reduced.
pub cwr: bool,
/// ECN-Echo.
pub ece: bool,
/// Indicates the Urgent pointer field is significant.
pub urg: bool,
/// Indicates that the Acknowledgment field is significant.
pub ack: bool,
/// Asks to push the buffered data to the receiving application.
pub psh: bool,
/// Reset the connection.
pub rst: bool,
/// Synchronize sequence numbers.
pub syn: bool,
/// No more data from sender.
pub fin: bool,
}
impl TcpFlags {
fn of_int(d: u16) -> TcpFlags {
TcpFlags {
ns: test_bit(0, d as u64),
cwr: test_bit(1, d as u64),
ece: test_bit(2, d as u64),
urg: test_bit(3, d as u64),
ack: test_bit(4, d as u64),
psh: test_bit(5, d as u64),
rst: test_bit(6, d as u64),
syn: test_bit(7, d as u64),
fin: test_bit(8, d as u64),
}
}
}
/// TCP frame of a packet.
#[derive(Debug)]
pub struct Tcp {
pub src: u16,
pub dst: u16,
pub seq: u32,
pub ack: u32,
pub offset: u8,
pub flags: TcpFlags,
pub window: u16,
pub chksum: u16,
pub urgent: u16,
pub payload: Vec<u8>,
}
#[repr(packed)]
struct TcpNet(u16, u16, u32, u32, u16, u16, u16, u16);
impl Tcp {
fn parse(bytes: &mut Cursor<Vec<u8>>) -> Option<Tcp> {
if bytes.get_ref().len() < size_of::<TcpNet>() {
return None;
}
let src = bytes.read_u16::<BigEndian>().unwrap();
let dst = bytes.read_u16::<BigEndian>().unwrap();
let seq = bytes.read_u32::<BigEndian>().unwrap();
let ack = bytes.read_u32::<BigEndian>().unwrap();
let offset = bytes.read_u16::<BigEndian>().unwrap();
let flags = TcpFlags::of_int(offset);
let offset = (offset >> 12) as u8 & 0x0f;
let window = bytes.read_u16::<BigEndian>().unwrap();
let chksum = bytes.read_u16::<BigEndian>().unwrap();
let urgent = bytes.read_u16::<BigEndian>().unwrap();
let payload = bytes.fill_buf().unwrap().to_vec();
Some(Tcp {
src: src,
dst: dst,
seq: seq,
ack: ack,
offset: offset,
flags: flags,
window: window,
chksum: chksum,
urgent: urgent,
payload: payload,
})
}
}
/// UDP frame of a packet.
#[derive(Debug)]
pub struct Udp {
pub src: u16,
pub dst: u16,
pub chksum: u16,
pub payload: Vec<u8>,
}
impl Udp {
fn size_of() -> usize {
8
}
fn parse(bytes: &mut Cursor<Vec<u8>>) -> Option<Udp> {
if bytes.get_ref().len() < Self::size_of() {
return None;
}
let src = bytes.read_u16::<BigEndian>().unwrap();
let dst = bytes.read_u16::<BigEndian>().unwrap();
let chksum = bytes.read_u16::<BigEndian>().unwrap();
let payload = bytes.fill_buf().unwrap().to_vec();
Some(Udp {
src: src,
dst: dst,
chksum: chksum,
payload: payload,
})
}
}
/// ICMP frame of a packet.
#[derive(Debug)]
pub struct Icmp {
pub typ: u8,
pub code: u8,
pub chksum: u16,
pub payload: Vec<u8>,
}
impl Icmp {
fn size_of() -> usize {
4
}
fn parse(bytes: &mut Cursor<Vec<u8>>) -> Option<Icmp> {
if bytes.get_ref().len() < Self::size_of() {
return None;
}
let typ = bytes.read_u8().unwrap();
let code = bytes.read_u8().unwrap();
let chksum = bytes.read_u16::<BigEndian>().unwrap();
let payload = bytes.fill_buf().unwrap().to_vec();
Some(Icmp {
typ: typ,
code: code,
chksum: chksum,
payload: payload,
})
}
}
/// Represents packets at the transport protocol level, which are encapsulated
/// within the IPv4 payload. At present, we only support TCP, UDP, and ICMP
/// explicitly; otherwise, the raw bytes and IPv4 protocol number are provided.
#[derive(Debug)]
pub enum Tp {
Tcp(Tcp),
Udp(Udp),
Icmp(Icmp),
Unparsable(u8, Vec<u8>),
}
/// The type of IPv4 flags.
#[derive(Debug)]
pub struct Flags {
pub dont_fragment: bool,
pub more_fragments: bool,
}
impl Flags {
fn of_int(flags: u32) -> Flags {
Flags {
dont_fragment: test_bit(1, flags as u64),
more_fragments: test_bit(2, flags as u64),
}
}
}
/// IPv4 frame of a packet.
#[derive(Debug)]
pub struct Ip {
pub tos: u8,
pub ident: u16,
pub flags: Flags,
pub frag: u16,
pub ttl: u8,
pub chksum: u16,
pub src: u32,
pub dst: u32,
pub options: Vec<u8>,
pub tp: Tp,
}
#[repr(u8)]
enum IpProto {
IpICMP = 0x01,
IpTCP = 0x06,
IpUDP = 0x11,
}
#[repr(packed)]
struct IpNet(u8, u8, u16, u16, u16, u8, u8, u16, u32, u32);
impl Ip {
fn parse(bytes: &mut Cursor<Vec<u8>>) -> Option<Ip> {
if bytes.get_ref().len() < size_of::<IpNet>() {
return None;
}
let vhl = bytes.read_u8().unwrap();
if (vhl >> 4) != 4 {
return None;
}
let ihl = vhl & 0x0f;
let tos = bytes.read_u8().unwrap();
bytes.consume(2);
let ident = bytes.read_u16::<BigEndian>().unwrap();
let frag = bytes.read_u16::<BigEndian>().unwrap();
let flags = Flags::of_int((frag as u32) >> 13);
let ttl = bytes.read_u8().unwrap();
let proto = bytes.read_u8().unwrap();
let chksum = bytes.read_u16::<BigEndian>().unwrap();
let src = bytes.read_u32::<BigEndian>().unwrap();
let dst = bytes.read_u32::<BigEndian>().unwrap();
let options_len = (ihl * 4) as usize - size_of::<IpNet>();
let mut options = vec![0; options_len];
bytes.read_exact(&mut options).unwrap();
let tp = match proto {
t if t == (IpProto::IpICMP as u8) => {
let icmp = Icmp::parse(bytes);
if icmp.is_some() {
Tp::Icmp(icmp.unwrap())
} else {
Tp::Unparsable(proto, bytes.fill_buf().unwrap().to_vec())
}
}
t if t == (IpProto::IpTCP as u8) => {
let tcp = Tcp::parse(bytes);
if tcp.is_some() {
Tp::Tcp(tcp.unwrap())
} else {
Tp::Unparsable(proto, bytes.fill_buf().unwrap().to_vec())
}
}
t if t == (IpProto::IpUDP as u8) => {
let udp = Udp::parse(bytes);
if udp.is_some() {
Tp::Udp(udp.unwrap())
} else {
Tp::Unparsable(proto, bytes.fill_buf().unwrap().to_vec())
}
}
_ => Tp::Unparsable(proto, bytes.fill_buf().unwrap().to_vec()),
};
Some(Ip {
tos: tos,
ident: ident,
flags: flags,
frag: frag,
ttl: ttl,
chksum: chksum,
src: src,
dst: dst,
options: options,
tp: tp,
})
}
}
/// Address resolution protocol (ARP) packet payload.
#[derive(Debug)]
pub enum Arp {
Query(u64, u32, u32),
Reply(u64, u32, u64, u32),
}
#[repr(packed)]
struct ArpNet(u16, u16, u8, u8, u16, [u8; 6], u32, [u8; 6], u32);
impl Arp {
fn parse(bytes: &mut Cursor<Vec<u8>>) -> Option<Arp> {
if bytes.get_ref().len() < size_of::<ArpNet>() {
return None;
}
bytes.consume(6);
let oper = bytes.read_u16::<BigEndian>().unwrap();
let mut sha: [u8; 6] = [0; 6];
for i in 0..6 {
sha[i] = bytes.read_u8().unwrap();
}
let spa = bytes.read_u32::<BigEndian>().unwrap();
let mut tha: [u8; 6] = [0; 6];
for i in 0..6 {
tha[i] = bytes.read_u8().unwrap();
}
let tpa = bytes.read_u32::<BigEndian>().unwrap();
match oper {
0x0001 => Some(Arp::Query(mac_of_bytes(sha), spa, tpa)),
0x0002 => Some(Arp::Reply(mac_of_bytes(sha), spa, mac_of_bytes(tha), tpa)),
_ => None,
}
}
}
/// Represents a packet at the network protocol level.
#[derive(Debug)]
pub enum Nw {
Ip(Ip),
Arp(Arp),
Unparsable(u16, Vec<u8>),
}
/// Represents a packet at the ethernet protocol level.
#[derive(Debug)]
pub struct Packet {
pub dl_src: u64,
pub dl_dst: u64,
pub dl_vlan: Option<u16>,
pub dl_vlan_dei: bool,
pub dl_vlan_pcp: u8,
pub nw: Nw,
}
#[repr(u16)]
enum EthTyp {
EthTypIP = 0x0800,
EthTypARP = 0x0806,
EthTypVLAN = 0x8100,
}
impl Packet {
pub fn parse(buf: &[u8]) -> Packet {
let mut bytes = Cursor::new(buf.to_vec());
let mut dst: [u8; 6] = [0; 6];
let mut src: [u8; 6] = [0; 6];
for i in 0..6 {
dst[i] = bytes.read_u8().unwrap();
}
for i in 0..6 {
src[i] = bytes.read_u8().unwrap();
}
let typ = bytes.read_u16::<BigEndian>().unwrap();
let (tag, dei, pcp, typ) = match typ {
// เช็คว่ามี 802.1Q ไหม โดยการเทียบ tpid 0x8100
t if t == (EthTyp::EthTypVLAN as u16) => {
let tag_and_pcp = bytes.read_u16::<BigEndian>().unwrap();
// 0xfff is 12 bit, 1f is 4 bit
// ลบ จาก 16 bit เหลือ 12 bit
// ทำการหั่น 802.1Q ออก โดยใช้ and bit operator
// 32 bit ประกอบไปด้วย
// 3 bit is pcp
// 1 bit is dei
// 12 bit is vid
let tag = tag_and_pcp & 0xfff; // vid 12 bit
let dei = (tag_and_pcp & 0x1000) > 0; // dei 1 bit, it means True or False
// pcp โดยใช้การเลื่อน bit (shift bit) ให้เลือ 3 bit หน้าสุด
let pcp = tag_and_pcp >> 13;
// ถัดจาก 802.1Q header จะเป็น EtherType/size 2 byte or 16 bit
let typ = bytes.read_u16::<BigEndian>().unwrap();
(Some(tag), dei, pcp as u8, typ)
}
_ => (None, false, 0x0, typ),
};
let nw_header = match typ {
// EthTypIP = 0x0800,
t if t == (EthTyp::EthTypIP as u16) => {
let ip = Ip::parse(&mut bytes);
if ip.is_some() {
Nw::Ip(ip.unwrap())
} else {
Nw::Unparsable(typ, bytes.fill_buf().unwrap().to_vec())
}
}
// EthTypARP = 0x0806,
t if t == (EthTyp::EthTypARP as u16) => {
let arp = Arp::parse(&mut bytes);
if arp.is_some() {
Nw::Arp(arp.unwrap())
} else {
Nw::Unparsable(typ, bytes.fill_buf().unwrap().to_vec())
}
}
_ => Nw::Unparsable(typ, bytes.fill_buf().unwrap().to_vec()),
};
Packet {
dl_src: mac_of_bytes(src),
dl_dst: mac_of_bytes(dst),
dl_vlan: tag,
dl_vlan_dei: dei,
dl_vlan_pcp: pcp,
nw: nw_header,
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment