use crate::ast::*;
use alloc::vec::Vec;
pub fn build_openflow_payload(spec: &OpenflowSpec, payload: &[u8]) -> (Vec<u8>, u16) {
let version = spec.version.unwrap_or(4); let resolved_type = spec.of_type.unwrap_or(if spec.dpid.is_some() {
OpenflowType::FeaturesReply
} else if spec.table_id.is_some() || spec.priority.is_some() {
OpenflowType::FlowMod
} else {
OpenflowType::Hello
});
let of_type = match resolved_type {
OpenflowType::Hello => 0,
OpenflowType::EchoReq => 2,
OpenflowType::EchoReply => 3,
OpenflowType::FeaturesReq => 5,
OpenflowType::FeaturesReply => 6,
OpenflowType::PacketIn => 10,
OpenflowType::FlowMod => 14,
OpenflowType::PacketOut => 13,
};
let mut body = Vec::new();
if payload.is_empty() {
match resolved_type {
OpenflowType::FeaturesReply => {
let dpid = spec.dpid.unwrap_or(0x0000_0000_0000_0001);
body.extend_from_slice(&dpid.to_be_bytes());
body.extend_from_slice(&256_u32.to_be_bytes()); body.push(spec.table_id.unwrap_or(254)); body.push(0); body.extend_from_slice(&[0, 0]); body.extend_from_slice(&0x0000_004f_u32.to_be_bytes()); body.extend_from_slice(&(spec.priority.unwrap_or(0) as u32).to_be_bytes()); }
OpenflowType::FlowMod => {
let cookie = spec.dpid.unwrap_or(0);
body.extend_from_slice(&cookie.to_be_bytes()); body.extend_from_slice(&0_u64.to_be_bytes()); body.push(spec.table_id.unwrap_or(0)); body.push(0); body.extend_from_slice(&0_u16.to_be_bytes()); body.extend_from_slice(&0_u16.to_be_bytes()); body.extend_from_slice(&spec.priority.unwrap_or(100).to_be_bytes()); body.extend_from_slice(&0xFFFF_FFFF_u32.to_be_bytes()); body.extend_from_slice(&0xFFFF_FFFF_u32.to_be_bytes()); body.extend_from_slice(&0xFFFF_FFFF_u32.to_be_bytes()); body.extend_from_slice(&0_u16.to_be_bytes()); body.extend_from_slice(&[0, 0]); body.extend_from_slice(&1_u16.to_be_bytes());
body.extend_from_slice(&4_u16.to_be_bytes());
body.extend_from_slice(&[0, 0, 0, 0]);
}
_ => {
if let Some(dpid) = spec.dpid {
body.extend_from_slice(&dpid.to_be_bytes());
}
if let Some(table_id) = spec.table_id {
body.push(table_id);
}
if let Some(priority) = spec.priority {
body.extend_from_slice(&priority.to_be_bytes());
}
}
}
} else {
body.extend_from_slice(payload);
}
let total_len = (8 + body.len()) as u16;
let mut of = Vec::with_capacity(total_len as usize);
of.push(version);
of.push(of_type);
of.extend_from_slice(&total_len.to_be_bytes());
of.extend_from_slice(&spec.xid.unwrap_or(1).to_be_bytes());
of.extend_from_slice(&body);
(of, 6653)
}