Commit 282cba84 authored by Nawasan Wisitsingkhon's avatar Nawasan Wisitsingkhon

pepare for sending message and add new support more message

parent 12d6f072
use std::io::Read; use std::io::Read;
use std::net::TcpListener; use std::net::TcpListener;
use tenjin::openflow::events::packet_in::PacketInEvent; use tenjin::openflow::events::packet_in::PacketInEvent;
use tenjin::openflow::{Controller, Msg, OfpHeader}; use tenjin::openflow::{Controller, OfpMsg, OfpHeader};
extern crate byteorder; extern crate byteorder;
...@@ -31,16 +31,16 @@ fn main() -> Result<(), std::io::Error> { ...@@ -31,16 +31,16 @@ fn main() -> Result<(), std::io::Error> {
let length_payload = packet.size(); let length_payload = packet.size();
let mut payload = vec![0u8; length_payload]; let mut payload = vec![0u8; length_payload];
stream.read(&mut payload)?; stream.read(&mut payload)?;
let message = Msg::parse(packet.message); let message = OfpMsg::parse(packet.message);
match message { match message {
// 0 is Hello message // 0 is Hello message
Msg::Hello => { OfpMsg::Hello => {
// after get Hello, send fetureReq // after get Hello, send fetureReq
controller.feture_req(packet.xid, &mut stream); controller.fetures_req(packet.xid, &mut stream);
println!("Hello event"); println!("Hello event");
} }
Msg::PacketIn => { OfpMsg::PacketIn => {
controller.packet_in( controller.packet_in(
packet.xid, packet.xid,
PacketInEvent::parse(&payload), PacketInEvent::parse(&payload),
......
use std::{collections::HashMap, io::Write, mem::size_of, net::TcpStream}; use std::{collections::HashMap, io::Write, net::TcpStream};
use super::{events::PacketInEvent, OfpHeader}; use super::{
events::{FeaturesReq, HelloEvent, PacketInEvent},
trait_marshal::MessageMarshal,
OfpHeader,
};
pub struct Controller { pub struct Controller {
version: u8, version: u8,
...@@ -15,32 +19,37 @@ impl Controller { ...@@ -15,32 +19,37 @@ impl Controller {
mac_to_port: HashMap::new(), mac_to_port: HashMap::new(),
} }
} }
pub fn send_msg<T: MessageMarshal>(&self, msg: T, xid: u32, stream: &mut TcpStream) {
let mut header_bytes: Vec<u8> = Vec::new();
let mut body_bytes: Vec<u8> = Vec::new();
msg.marshal(&mut body_bytes);
let ofpheader = OfpHeader::new(
self.version,
msg.msg_code() as u8,
body_bytes.len() as u16,
xid,
);
ofpheader.marshal(&mut header_bytes);
header_bytes.append(&mut body_bytes);
let _ = stream.write_all(&header_bytes);
}
/**
* example of sending message
*/
pub fn hello(&self, stream: &mut TcpStream) { pub fn hello(&self, stream: &mut TcpStream) {
let header = OfpHeader::new(self.version, 0, size_of::<OfpHeader>() as u16, 0); let hello_msg = HelloEvent::new();
let mut bytes: Vec<u8> = Vec::new(); self.send_msg(hello_msg, 0, stream);
header.marshal(&mut bytes);
stream.write_all(&bytes).unwrap();
} }
pub fn feture_req(&self, xid: u32, stream: &mut TcpStream) { pub fn fetures_req(&self, xid: u32, stream: &mut TcpStream) {
let header = OfpHeader::new(self.version, 5, 8, xid); let fetreq_msg = FeaturesReq::new();
let mut bytes: Vec<u8> = Vec::new(); self.send_msg(fetreq_msg, xid, stream);
header.marshal(&mut bytes);
stream.write_all(&bytes).unwrap();
} }
pub fn packet_in(&mut self, xid: u32, packetin: PacketInEvent, stream: &mut TcpStream) { pub fn packet_in(&mut self, xid: u32, packetin: PacketInEvent, stream: &mut TcpStream) {
let ether = packetin.payload; let ether = packetin.payload;
self.mac_to_port.insert(ether.mac_src, packetin.port); self.mac_to_port.insert(ether.mac_src, packetin.port);
} }
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 crate::openflow::trait_marshal::MessageMarshal;
pub struct FeaturesReq {}
impl FeaturesReq {
pub fn new() -> Self {
FeaturesReq {}
}
}
impl MessageMarshal for FeaturesReq {
fn marshal(&self, _: &mut Vec<u8>) {}
fn msg_code(&self) -> crate::openflow::OfpMsg {
crate::openflow::OfpMsg::FeaturesReq
}
fn size_of(&self) -> usize {
0
}
}
pub enum FlowModCommand { pub enum FlowModCommand {
Add, Add = 0,
Modify, Modify = 1,
ModifyStrict, ModifyStrict = 2,
Delete, Delete = 3,
DeleteStrict, DeleteStrict = 4,
Unparsable, Unparsable = -1,
} }
impl FlowModCommand { impl FlowModCommand {
pub fn to_number(&self) -> usize {
match self {
FlowModCommand::Add => Self::Add as usize,
FlowModCommand::Modify => Self::Modify as usize,
FlowModCommand::ModifyStrict => Self::ModifyStrict as usize,
FlowModCommand::Delete => Self::Delete as usize,
FlowModCommand::DeleteStrict => Self::DeleteStrict as usize,
FlowModCommand::Unparsable => Self::Unparsable as usize,
}
}
pub fn parse(byte: u16) -> Self { pub fn parse(byte: u16) -> Self {
match byte { match byte {
0 => Self::Add, 0 => Self::Add,
......
...@@ -201,3 +201,23 @@ impl FlowAction { ...@@ -201,3 +201,23 @@ impl FlowAction {
} }
} }
} }
impl Clone for FlowAction {
fn clone(&self) -> Self {
match self {
Self::Oputput(v) => Self::Oputput(v.clone()),
Self::SetDlVlan(v) => Self::SetDlVlan(v.clone()),
Self::SetDlVlanPcp(v) => Self::SetDlVlanPcp(v.clone()),
Self::SetDlSrc(v) => Self::SetDlSrc(v.clone()),
Self::SetDlDest(v) => Self::SetDlDest(v.clone()),
Self::SetIpSrc(v) => Self::SetIpSrc(v.clone()),
Self::SetIpDes(v) => Self::SetIpDes(v.clone()),
Self::SetTos(v) => Self::SetTos(v.clone()),
Self::SetTpSrc(v) => Self::SetTpSrc(v.clone()),
Self::SetTpDest(v) => Self::SetTpDest(v.clone()),
Self::Enqueue(v, arg1) => Self::Enqueue(v.clone(), arg1.clone()),
Self::Unparsable => Self::Unparsable,
}
}
}
\ No newline at end of file
...@@ -2,7 +2,7 @@ use std::io::Cursor; ...@@ -2,7 +2,7 @@ use std::io::Cursor;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use crate::openflow::{OfpPort, PseudoPort}; use crate::openflow::{trait_marshal::MessageMarshal, OfpMsg, OfpPort, PseudoPort};
use super::{FlowAction, FlowModCommand, MatchFields}; use super::{FlowAction, FlowModCommand, MatchFields};
...@@ -25,7 +25,7 @@ impl Timeout { ...@@ -25,7 +25,7 @@ impl Timeout {
} }
} }
pub struct FlowMod { pub struct FlowModEvent {
command: FlowModCommand, command: FlowModCommand,
match_fields: MatchFields, match_fields: MatchFields,
priority: u16, priority: u16,
...@@ -39,26 +39,23 @@ pub struct FlowMod { ...@@ -39,26 +39,23 @@ pub struct FlowMod {
check_overlap: bool, check_overlap: bool,
} }
impl FlowMod { impl FlowModEvent {
pub fn get_controller_last(actions: Vec<FlowAction>) -> Vec<FlowAction> { pub fn get_controller_last(&self) -> Vec<FlowAction> {
let mut not_ctrl: Vec<FlowAction> = Vec::new(); let mut not_ctrl: Vec<FlowAction> = Vec::new();
let mut is_ctrl: Vec<FlowAction> = Vec::new(); let mut is_ctrl: Vec<FlowAction> = Vec::new();
for act in actions { for act in &self.actions {
match act { match act {
FlowAction::Oputput(PseudoPort::Controller(_)) => { FlowAction::Oputput(PseudoPort::Controller(_)) => {
is_ctrl.push(act); is_ctrl.push(act.clone());
} }
_ => not_ctrl.push(act), _ => not_ctrl.push(act.clone()),
} }
} }
not_ctrl.append(&mut is_ctrl); not_ctrl.append(&mut is_ctrl);
not_ctrl not_ctrl
} }
pub fn size_of() -> usize { pub fn parse(buf: &[u8]) -> FlowModEvent {
24
}
pub fn parse(buf: &[u8]) -> FlowMod {
let mut bytes = Cursor::new(buf.to_vec()); let mut bytes = Cursor::new(buf.to_vec());
let match_fields = MatchFields::parse(&mut bytes); let match_fields = MatchFields::parse(&mut bytes);
let cookie = bytes.read_u64::<BigEndian>().unwrap(); let cookie = bytes.read_u64::<BigEndian>().unwrap();
...@@ -70,7 +67,7 @@ impl FlowMod { ...@@ -70,7 +67,7 @@ impl FlowMod {
let out_port = PseudoPort::parse(bytes.read_u16::<BigEndian>().unwrap()); let out_port = PseudoPort::parse(bytes.read_u16::<BigEndian>().unwrap());
let flags = bytes.read_u16::<BigEndian>().unwrap(); let flags = bytes.read_u16::<BigEndian>().unwrap();
let actions = FlowAction::parse_sequence(&mut bytes); let actions = FlowAction::parse_sequence(&mut bytes);
FlowMod { FlowModEvent {
command, command,
match_fields, match_fields,
cookie, cookie,
...@@ -89,30 +86,35 @@ impl FlowMod { ...@@ -89,30 +86,35 @@ impl FlowMod {
check_overlap: flags & 2 != 0, check_overlap: flags & 2 != 0,
} }
} }
pub fn marshal(flowmod: FlowMod, bytes: &mut Vec<u8>) { }
flowmod.match_fields.marshal(bytes);
let _ = bytes.write_u64::<BigEndian>(flowmod.cookie); impl MessageMarshal for FlowModEvent {
let _ = bytes.write_u16::<BigEndian>(flowmod.command as u16); fn size_of(&self) -> usize {
let _ = bytes.write_u16::<BigEndian>(flowmod.idle_timeout.to_int()); 24
let _ = bytes.write_u16::<BigEndian>(flowmod.hard_timeout.to_int()); }
let _ = bytes.write_u16::<BigEndian>(flowmod.priority); fn msg_code(&self) -> OfpMsg {
let _ = bytes.write_i32::<BigEndian>(match flowmod.apply_to_packet { OfpMsg::FlowMod
}
fn marshal(&self, bytes: &mut Vec<u8>) {
self.match_fields.marshal(bytes);
let _ = bytes.write_u64::<BigEndian>(self.cookie);
let _ = bytes.write_u16::<BigEndian>(self.command.to_number() as u16);
let _ = bytes.write_u16::<BigEndian>(self.idle_timeout.to_int());
let _ = bytes.write_u16::<BigEndian>(self.hard_timeout.to_int());
let _ = bytes.write_u16::<BigEndian>(self.priority);
let _ = bytes.write_i32::<BigEndian>(match self.apply_to_packet {
None => -1, None => -1,
Some(buf_id) => buf_id as i32, Some(buf_id) => buf_id as i32,
}); });
match flowmod.out_port { match self.out_port.as_ref() {
None => bytes.write_u16::<BigEndian>(OfpPort::None as u16).unwrap(), None => bytes.write_u16::<BigEndian>(OfpPort::None as u16).unwrap(),
Some(p) => p.marshal(bytes), Some(p) => p.marshal(bytes),
} }
let _ = bytes.write_u16::<BigEndian>( let _ = bytes.write_u16::<BigEndian>(
(if flowmod.check_overlap { 1 << 1 } else { 0 }) (if self.check_overlap { 1 << 1 } else { 0 })
| (if flowmod.notify_when_removed { | (if self.notify_when_removed { 1 << 0 } else { 0 }),
1 << 0
} else {
0
}),
); );
for act in FlowMod::get_controller_last(flowmod.actions) { for act in self.get_controller_last() {
match act { match act {
FlowAction::Oputput(PseudoPort::Table) => { FlowAction::Oputput(PseudoPort::Table) => {
panic!("Openflow table not allowed") panic!("Openflow table not allowed")
......
...@@ -75,7 +75,7 @@ pub struct MatchFields { ...@@ -75,7 +75,7 @@ pub struct MatchFields {
} }
impl MatchFields { impl MatchFields {
pub fn marshal(self, bytes: &mut Vec<u8>) { pub fn marshal(&self, bytes: &mut Vec<u8>) {
let mut match_f = 0u32; let mut match_f = 0u32;
match_f = set_bit(match_f, 0, self.in_port.is_some()); match_f = set_bit(match_f, 0, self.in_port.is_some());
match_f = set_bit(match_f, 1, self.vlan_vid.is_some()); match_f = set_bit(match_f, 1, self.vlan_vid.is_some());
...@@ -85,8 +85,8 @@ impl MatchFields { ...@@ -85,8 +85,8 @@ impl MatchFields {
match_f = set_bit(match_f, 5, self.protocol.is_some()); match_f = set_bit(match_f, 5, self.protocol.is_some());
match_f = set_bit(match_f, 6, self.ip_src.is_some()); match_f = set_bit(match_f, 6, self.ip_src.is_some());
match_f = set_bit(match_f, 7, self.ip_dest.is_some()); match_f = set_bit(match_f, 7, self.ip_dest.is_some());
match_f = MatchFields::set_nw_mask(match_f, 8, self.ip_src.unwrap().ip); match_f = MatchFields::set_nw_mask(match_f, 8, self.ip_src.as_ref().unwrap().ip);
match_f = MatchFields::set_nw_mask(match_f, 14, self.ip_dest.unwrap().ip); match_f = MatchFields::set_nw_mask(match_f, 14, self.ip_dest.as_ref().unwrap().ip);
match_f = set_bit(match_f, 20, self.vlan_pcp.is_some()); match_f = set_bit(match_f, 20, self.vlan_pcp.is_some());
match_f = set_bit(match_f, 21, self.tos.is_some()); match_f = set_bit(match_f, 21, self.tos.is_some());
bytes.write_u32::<BigEndian>(match_f).unwrap(); bytes.write_u32::<BigEndian>(match_f).unwrap();
......
pub mod flow_mod_handler; pub mod flow_mod_handler;
pub use flow_mod_handler::FlowModEvent;
pub mod command; pub mod command;
pub use command::FlowModCommand; pub use command::FlowModCommand;
...@@ -11,3 +12,4 @@ pub use flow_actions_type::FlowActionType; ...@@ -11,3 +12,4 @@ pub use flow_actions_type::FlowActionType;
pub mod match_fields; pub mod match_fields;
pub use match_fields::{Mask, MatchFields}; pub use match_fields::{Mask, MatchFields};
use crate::openflow::{trait_marshal::MessageMarshal, OfpMsg};
pub struct HelloEvent {}
impl HelloEvent {
pub fn new() -> Self {
HelloEvent {}
}
}
impl MessageMarshal for HelloEvent {
fn marshal(&self, _: &mut Vec<u8>) {}
fn msg_code(&self) -> crate::openflow::OfpMsg {
OfpMsg::Hello
}
fn size_of(&self) -> usize {
0
}
}
...@@ -2,4 +2,10 @@ pub mod packet_in; ...@@ -2,4 +2,10 @@ pub mod packet_in;
pub use packet_in::{PacketInEvent, PacketInReason}; pub use packet_in::{PacketInEvent, PacketInReason};
pub mod flow_mod; pub mod flow_mod;
pub use flow_mod::{FlowAction, FlowModEvent};
pub mod hello;
pub use hello::HelloEvent;
pub mod features_req;
pub use features_req::FeaturesReq;
\ No newline at end of file
...@@ -17,7 +17,7 @@ impl OfpHeader { ...@@ -17,7 +17,7 @@ impl OfpHeader {
Self { Self {
version, version,
message, message,
length, length: length + 8,
xid, xid,
} }
} }
......
pub enum Msg { pub enum OfpMsg {
Hello, Hello = 0,
PacketIn, FeaturesReq = 5,
NotFound, PacketIn = 8,
FlowMod = 14,
NotFound = -1,
} }
impl Msg { impl OfpMsg {
pub fn parse(message_code: u8) -> Self { pub fn parse(message_code: u8) -> Self {
match message_code { match message_code {
0 => Msg::Hello, 0 => OfpMsg::Hello,
8 => Msg::PacketIn, 8 => OfpMsg::PacketIn,
_ => Msg::NotFound, _ => OfpMsg::NotFound,
} }
} }
} }
...@@ -2,7 +2,7 @@ pub mod header; ...@@ -2,7 +2,7 @@ pub mod header;
pub use header::OfpHeader; pub use header::OfpHeader;
pub mod message; pub mod message;
pub use message::Msg; pub use message::OfpMsg;
pub mod controller; pub mod controller;
pub use controller::Controller; pub use controller::Controller;
...@@ -11,3 +11,5 @@ pub mod events; ...@@ -11,3 +11,5 @@ pub mod events;
pub mod ofp_port; pub mod ofp_port;
pub use ofp_port::{OfpPort, PseudoPort}; pub use ofp_port::{OfpPort, PseudoPort};
pub mod trait_marshal;
\ No newline at end of file
...@@ -68,3 +68,19 @@ impl PseudoPort { ...@@ -68,3 +68,19 @@ impl PseudoPort {
let _ = bytes.write_u16::<BigEndian>(port); let _ = bytes.write_u16::<BigEndian>(port);
} }
} }
impl Clone for PseudoPort {
fn clone(&self) -> Self {
match self {
Self::PhysicalPort(arg0) => Self::PhysicalPort(arg0.clone()),
Self::InPort => Self::InPort,
Self::Table => Self::Table,
Self::Normal => Self::Normal,
Self::Flood => Self::Flood,
Self::AllPorts => Self::AllPorts,
Self::Controller(arg0) => Self::Controller(arg0.clone()),
Self::Local => Self::Local,
Self::Unsupport => Self::Unsupport,
}
}
}
\ No newline at end of file
use super::OfpMsg;
/**
* the trait for parse value to bytes.
* for use with Controller's send_msg.
*/
pub trait MessageMarshal {
fn marshal(&self, bytes: &mut Vec<u8>);
fn msg_code(&self) -> OfpMsg;
fn size_of(&self) -> usize;
}
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