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::net::TcpListener;
use tenjin::openflow::events::packet_in::PacketInEvent;
use tenjin::openflow::{Controller, Msg, OfpHeader};
use tenjin::openflow::{Controller, OfpMsg, OfpHeader};
extern crate byteorder;
......@@ -31,16 +31,16 @@ fn main() -> Result<(), std::io::Error> {
let length_payload = packet.size();
let mut payload = vec![0u8; length_payload];
stream.read(&mut payload)?;
let message = Msg::parse(packet.message);
let message = OfpMsg::parse(packet.message);
match message {
// 0 is Hello message
Msg::Hello => {
OfpMsg::Hello => {
// after get Hello, send fetureReq
controller.feture_req(packet.xid, &mut stream);
controller.fetures_req(packet.xid, &mut stream);
println!("Hello event");
}
Msg::PacketIn => {
OfpMsg::PacketIn => {
controller.packet_in(
packet.xid,
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 {
version: u8,
......@@ -15,32 +19,37 @@ impl Controller {
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) {
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();
let hello_msg = HelloEvent::new();
self.send_msg(hello_msg, 0, stream);
}
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 fetures_req(&self, xid: u32, stream: &mut TcpStream) {
let fetreq_msg = FeaturesReq::new();
self.send_msg(fetreq_msg, xid, stream);
}
pub fn packet_in(&mut self, xid: u32, packetin: PacketInEvent, stream: &mut TcpStream) {
let ether = packetin.payload;
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 {
Add,
Modify,
ModifyStrict,
Delete,
DeleteStrict,
Unparsable,
Add = 0,
Modify = 1,
ModifyStrict = 2,
Delete = 3,
DeleteStrict = 4,
Unparsable = -1,
}
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 {
match byte {
0 => Self::Add,
......
......@@ -28,7 +28,7 @@ pub enum FlowAction {
}
impl FlowAction {
pub fn to_action_code(&self) -> FlowActionType {
pub fn to_action_code(&self) -> FlowActionType {
match self {
FlowAction::Oputput(_) => FlowActionType::Output,
FlowAction::SetDlVlan(_) => FlowActionType::SetVlanId,
......@@ -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;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use crate::openflow::{OfpPort, PseudoPort};
use crate::openflow::{trait_marshal::MessageMarshal, OfpMsg, OfpPort, PseudoPort};
use super::{FlowAction, FlowModCommand, MatchFields};
......@@ -25,7 +25,7 @@ impl Timeout {
}
}
pub struct FlowMod {
pub struct FlowModEvent {
command: FlowModCommand,
match_fields: MatchFields,
priority: u16,
......@@ -39,26 +39,23 @@ pub struct FlowMod {
check_overlap: bool,
}
impl FlowMod {
pub fn get_controller_last(actions: Vec<FlowAction>) -> Vec<FlowAction> {
impl FlowModEvent {
pub fn get_controller_last(&self) -> Vec<FlowAction> {
let mut not_ctrl: Vec<FlowAction> = Vec::new();
let mut is_ctrl: Vec<FlowAction> = Vec::new();
for act in actions {
for act in &self.actions {
match act {
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
}
pub fn size_of() -> usize {
24
}
pub fn parse(buf: &[u8]) -> FlowMod {
pub fn parse(buf: &[u8]) -> FlowModEvent {
let mut bytes = Cursor::new(buf.to_vec());
let match_fields = MatchFields::parse(&mut bytes);
let cookie = bytes.read_u64::<BigEndian>().unwrap();
......@@ -70,7 +67,7 @@ impl FlowMod {
let out_port = PseudoPort::parse(bytes.read_u16::<BigEndian>().unwrap());
let flags = bytes.read_u16::<BigEndian>().unwrap();
let actions = FlowAction::parse_sequence(&mut bytes);
FlowMod {
FlowModEvent {
command,
match_fields,
cookie,
......@@ -89,30 +86,35 @@ impl FlowMod {
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);
let _ = bytes.write_u16::<BigEndian>(flowmod.command as u16);
let _ = bytes.write_u16::<BigEndian>(flowmod.idle_timeout.to_int());
let _ = bytes.write_u16::<BigEndian>(flowmod.hard_timeout.to_int());
let _ = bytes.write_u16::<BigEndian>(flowmod.priority);
let _ = bytes.write_i32::<BigEndian>(match flowmod.apply_to_packet {
}
impl MessageMarshal for FlowModEvent {
fn size_of(&self) -> usize {
24
}
fn msg_code(&self) -> OfpMsg {
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,
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(),
Some(p) => p.marshal(bytes),
}
let _ = bytes.write_u16::<BigEndian>(
(if flowmod.check_overlap { 1 << 1 } else { 0 })
| (if flowmod.notify_when_removed {
1 << 0
} else {
0
}),
(if self.check_overlap { 1 << 1 } else { 0 })
| (if self.notify_when_removed { 1 << 0 } else { 0 }),
);
for act in FlowMod::get_controller_last(flowmod.actions) {
for act in self.get_controller_last() {
match act {
FlowAction::Oputput(PseudoPort::Table) => {
panic!("Openflow table not allowed")
......
......@@ -75,7 +75,7 @@ pub struct MatchFields {
}
impl MatchFields {
pub fn marshal(self, bytes: &mut Vec<u8>) {
pub fn marshal(&self, bytes: &mut Vec<u8>) {
let mut match_f = 0u32;
match_f = set_bit(match_f, 0, self.in_port.is_some());
match_f = set_bit(match_f, 1, self.vlan_vid.is_some());
......@@ -85,8 +85,8 @@ impl MatchFields {
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, 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, 14, self.ip_dest.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.as_ref().unwrap().ip);
match_f = set_bit(match_f, 20, self.vlan_pcp.is_some());
match_f = set_bit(match_f, 21, self.tos.is_some());
bytes.write_u32::<BigEndian>(match_f).unwrap();
......
pub mod flow_mod_handler;
pub use flow_mod_handler::FlowModEvent;
pub mod command;
pub use command::FlowModCommand;
......@@ -11,3 +12,4 @@ pub use flow_actions_type::FlowActionType;
pub mod match_fields;
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;
pub use packet_in::{PacketInEvent, PacketInReason};
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 {
Self {
version,
message,
length,
length: length + 8,
xid,
}
}
......
pub enum Msg {
Hello,
PacketIn,
NotFound,
pub enum OfpMsg {
Hello = 0,
FeaturesReq = 5,
PacketIn = 8,
FlowMod = 14,
NotFound = -1,
}
impl Msg {
impl OfpMsg {
pub fn parse(message_code: u8) -> Self {
match message_code {
0 => Msg::Hello,
8 => Msg::PacketIn,
_ => Msg::NotFound,
0 => OfpMsg::Hello,
8 => OfpMsg::PacketIn,
_ => OfpMsg::NotFound,
}
}
}
......@@ -2,7 +2,7 @@ pub mod header;
pub use header::OfpHeader;
pub mod message;
pub use message::Msg;
pub use message::OfpMsg;
pub mod controller;
pub use controller::Controller;
......@@ -10,4 +10,6 @@ pub use controller::Controller;
pub mod events;
pub mod ofp_port;
pub use ofp_port::{OfpPort, PseudoPort};
\ No newline at end of file
pub use ofp_port::{OfpPort, PseudoPort};
pub mod trait_marshal;
\ No newline at end of file
......@@ -68,3 +68,19 @@ impl PseudoPort {
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