Commit 9de005e8 authored by Nawasan Wisitsingkhon's avatar Nawasan Wisitsingkhon

initial commit with setup

parents
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "tenjin"
version = "0.1.0"
dependencies = [
"byteorder",
]
[package]
name = "tenjin"
version = "0.1.0"
edition = "2021"
[lib]
name = "tenjin"
path = "src/lib.rs"
[[bin]]
name = "tenjin"
path = "src/main.rs"
[dependencies]
byteorder = "1.0.0"
\ No newline at end of file
This diff is collapsed.
# Tenjin SDN
## Goals
To understand The software-defined networking well, I trying to create a simple SDN with Rust language to support Openflow 1.0 first and 1.3 later.
## TODOs
- [ ] design structure of code and working.
- [ ] write more description in README.
\ No newline at end of file
pub mod openflow;
\ No newline at end of file
use tenjin::openflow::{Controller, Msg, OfpHeader};
use std::io::Read;
use std::net::TcpListener;
extern crate byteorder;
fn main() -> Result<(), std::io::Error> {
let controller = Controller::new(Controller::OFP_1_0);
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 =======================");
// after tcp is connected, it will send hello message
controller.hello(&mut stream);
// loop for receive data
loop {
// first receive with Openflow header 64 bit to buf
match stream.read(&mut buf) {
Ok(v) if v > 0 => {
let packet = OfpHeader::parse(&buf);
// length_payload is var to receive payload if the packet has
// and assign size by length
let length_payload = packet.size();
let mut payload = vec![0u8; length_payload];
stream.read(&mut payload)?;
let message = Msg::parse(packet.message, &payload);
match message {
// 0 is Hello message
Msg::Hello => {
// after get Hello, send fetureReq
controller.feture_req(packet.xid, &mut stream);
println!("Hello event");
}
Msg::PacketIn(b) => {
println!("PacketIn event");
}
_ => {
println!("others message");
}
}
}
Ok(_) | Err(_) => break,
}
}
println!("======================================================");
// });
}
Err(_) => {
// connection failed
panic!("Connection failed")
}
}
}
Ok(())
}
use std::{io::Write, mem::size_of, net::TcpStream};
use byteorder::{BigEndian, WriteBytesExt};
use super::OfpHeader;
pub struct Controller {
version: u8,
}
impl Controller {
pub const OFP_1_0: u8 = 1;
pub fn new(version: u8) -> Self {
Self { version }
}
pub fn hello(&self, stream: &mut TcpStream) {
let header = OfpHeader::new(self.version, 0, size_of::<OfpHeader>() as u16, 0);
let mut bytes: Vec<u8> = Vec::new();
header.marshal(&mut bytes);
stream.write_all(&bytes).unwrap();
}
pub fn feture_req(&self, xid: u32, stream: &mut TcpStream) {
let header = OfpHeader::new(self.version, 5, 8, xid);
let mut bytes: Vec<u8> = Vec::new();
header.marshal(&mut bytes);
stream.write_all(&bytes).unwrap();
}
pub fn send(&self, xid: u32, message: u8, payload: &Vec<u8>, stream: &mut TcpStream) {
let length = size_of::<OfpHeader>() + payload.len();
let header = OfpHeader::new(self.version, message, length as u16, xid);
let mut bytes: Vec<u8> = Vec::new();
header.marshal(&mut bytes);
stream.write_all(&bytes).unwrap();
}
}
use std::{io::Cursor, mem::size_of};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
pub struct OfpHeader {
pub version: u8,
pub message: u8,
pub length: u16,
pub xid: u32,
}
impl OfpHeader {
pub fn size(&self) -> usize {
return self.length as usize - size_of::<OfpHeader>();
}
pub fn new(version: u8, message: u8, length: u16, xid: u32) -> Self {
Self {
version,
message,
length,
xid,
}
}
pub fn parse(buf: &Vec<u8>) -> Self {
let mut buf_cursor = Cursor::new(buf);
// split data from header
let version = buf_cursor.read_u8().unwrap();
let message = buf_cursor.read_u8().unwrap();
// size is size of packet
let length = buf_cursor.read_u16::<BigEndian>().unwrap();
let xid = buf_cursor.read_u32::<BigEndian>().unwrap();
Self {
version,
message,
length,
xid,
}
}
pub fn marshal(&self, bytes: &mut Vec<u8>) {
bytes.write_u8(self.version).unwrap();
bytes.write_u8(self.message).unwrap();
bytes.write_u16::<BigEndian>(self.length).unwrap();
bytes.write_u32::<BigEndian>(self.xid).unwrap();
}
}
pub enum Msg {
Hello,
PacketIn(Vec<u8>),
NotFound,
}
impl Msg {
pub fn parse(message_code: u8, payload: &Vec<u8>) -> Self {
match message_code {
0 => Msg::Hello,
8 => Msg::PacketIn(payload.clone()),
_ => Msg::NotFound,
}
}
}
pub mod header;
pub use header::OfpHeader;
pub mod message;
pub use message::Msg;
pub mod controller;
pub use controller::Controller;
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