Commit 5e3ca5f4 authored by Nawasan Wisitsingkhon's avatar Nawasan Wisitsingkhon

add: packetOut event and payload

parent 117ebae2
......@@ -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,
......@@ -202,6 +202,31 @@ impl FlowAction {
}
}
pub trait SizeCheck {
fn size_of_sequence(&self) -> usize;
fn move_controller_last(&self) -> Vec<FlowAction>;
}
impl SizeCheck for Vec<FlowAction> {
fn size_of_sequence(&self) -> usize {
self.iter().fold(0, |acc, x| x.length() + acc)
}
fn move_controller_last(&self) -> Vec<FlowAction> {
let mut not_ctrl: Vec<FlowAction> = Vec::new();
let mut is_ctrl: Vec<FlowAction> = Vec::new();
for act in self {
match act {
FlowAction::Oputput(PseudoPort::Controller(_)) => {
is_ctrl.push(act.clone());
}
_ => not_ctrl.push(act.clone()),
}
}
not_ctrl.append(&mut is_ctrl);
not_ctrl
}
}
impl Clone for FlowAction {
fn clone(&self) -> Self {
......@@ -220,4 +245,4 @@ impl Clone for FlowAction {
Self::Unparsable => Self::Unparsable,
}
}
}
\ No newline at end of file
}
......@@ -7,7 +7,7 @@ use crate::openflow::{
OfpPort, PseudoPort,
};
use super::{FlowAction, FlowModCommand, MatchFields};
use super::{FlowAction, FlowModCommand, MatchFields, SizeCheck};
pub enum Timeout {
Permanent,
......@@ -58,20 +58,6 @@ impl FlowModEvent {
check_overlap: false,
}
}
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 &self.actions {
match act {
FlowAction::Oputput(PseudoPort::Controller(_)) => {
is_ctrl.push(act.clone());
}
_ => not_ctrl.push(act.clone()),
}
}
not_ctrl.append(&mut is_ctrl);
not_ctrl
}
pub fn parse(buf: &[u8]) -> FlowModEvent {
let mut bytes = Cursor::new(buf.to_vec());
......@@ -135,7 +121,7 @@ impl MessageMarshal for FlowModEvent {
(if self.check_overlap { 1 << 1 } else { 0 })
| (if self.notify_when_removed { 1 << 0 } else { 0 }),
);
for act in self.get_controller_last() {
for act in self.actions.move_controller_last() {
match act {
FlowAction::Oputput(PseudoPort::Table) => {
panic!("Openflow table not allowed")
......
......@@ -5,11 +5,10 @@ pub mod command;
pub use command::FlowModCommand;
pub mod flow_actions;
pub use flow_actions::FlowAction;
pub use flow_actions::{FlowAction, SizeCheck};
pub mod flow_actions_type;
pub use flow_actions_type::FlowActionType;
pub mod match_fields;
pub use match_fields::{Mask, MatchFields};
......@@ -2,6 +2,7 @@ pub mod packet_in;
pub use packet_in::{PacketInEvent, PacketInReason};
pub mod packet_out;
pub use packet_out::PacketOutEvent;
pub mod flow_mod;
pub use flow_mod::{FlowAction, FlowModEvent};
......@@ -13,4 +14,4 @@ pub mod features_req;
pub use features_req::FeaturesReq;
pub mod payload;
pub use payload::Payload;
\ No newline at end of file
pub use payload::Payload;
use super::Payload;
use std::io::{BufRead, Cursor, Read};
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use crate::openflow::{OfpPort, PseudoPort};
use super::{flow_mod::SizeCheck, FlowAction, Payload};
pub struct PacketOutEvent {
pub payload: Payload
}
\ No newline at end of file
pub payload: Payload,
pub port_id: Option<u16>,
pub actions: Vec<FlowAction>,
}
impl PacketOutEvent {
pub fn parse(buf: &Vec<u8>) -> Self {
let mut bytes = Cursor::new(buf);
let buf_id = match bytes
.read_i32::<BigEndian>()
.expect("cannot parse buf id in packetout")
{
-1 => None,
n => Some(n),
};
let in_port = bytes.read_u16::<BigEndian>().unwrap();
let action_len = bytes.read_u16::<BigEndian>().unwrap();
let mut actions_buf = vec![0; action_len as usize];
let _ = bytes.read_exact(&mut actions_buf);
let mut action_bytes = Cursor::new(actions_buf);
let actions = FlowAction::parse_sequence(&mut action_bytes);
Self {
payload: match buf_id {
None => Payload::NoBuffered(bytes.fill_buf().unwrap().to_vec()),
Some(n) => {
Payload::Buffered(n as u32, bytes.fill_buf().unwrap().to_ascii_lowercase())
}
},
port_id: {
if in_port == OfpPort::None as u16 {
None
} else {
Some(in_port)
}
},
actions,
}
}
pub fn marshal(&self, bytes: &mut Vec<u8>) {
let _ = bytes.write_i32::<BigEndian>(match self.payload {
Payload::Buffered(n, _) => n as i32,
Payload::NoBuffered(_) => -1,
});
match self.port_id {
Some(id) => {
PseudoPort::PhysicalPort(id).marshal(bytes);
}
None => {
let _ = bytes.write_u16::<BigEndian>(OfpPort::None as u16);
}
}
let _ = bytes.write_u16::<BigEndian>(self.actions.size_of_sequence() as u16);
for act in self.actions.move_controller_last() {
act.marshal(bytes);
}
self.payload.marshal(bytes);
}
}
use std::io::Write;
pub enum Payload {
Buffered(u32, Vec<u8>),
NoBuffered(Vec<u8>),
}
impl Payload {
pub fn marshal(&self, bytes: &mut Vec<u8>) {
match self {
Payload::Buffered(_, buf) | Payload::NoBuffered(buf) => {
let _ = bytes.write_all(&buf);
}
}
}
}
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