rovs_openflow/
packet_out.rs1use bytes::{BufMut, BytesMut};
7
8use crate::action::ActionList;
9use crate::message::{Header, Message, MessageType};
10use crate::packet_in::OFP_NO_BUFFER;
11use crate::Version;
12
13pub const OFPP_CONTROLLER: u32 = 0xffff_fffd;
15
16pub const OFPP_ANY: u32 = 0xffff_ffff;
18
19#[derive(Debug, Clone)]
21pub struct PacketOut {
22 buffer_id: u32,
24 in_port: u32,
26 actions: ActionList,
28 data: Vec<u8>,
30}
31
32impl PacketOut {
33 pub fn new() -> Self {
35 Self {
36 buffer_id: OFP_NO_BUFFER,
37 in_port: OFPP_CONTROLLER,
38 actions: ActionList::new(),
39 data: Vec::new(),
40 }
41 }
42
43 pub fn from_buffer(buffer_id: u32) -> Self {
45 Self {
46 buffer_id,
47 in_port: OFPP_CONTROLLER,
48 actions: ActionList::new(),
49 data: Vec::new(),
50 }
51 }
52
53 pub fn buffer_id(mut self, id: u32) -> Self {
55 self.buffer_id = id;
56 self
57 }
58
59 pub fn in_port(mut self, port: u32) -> Self {
61 self.in_port = port;
62 self
63 }
64
65 pub fn actions(mut self, actions: ActionList) -> Self {
67 self.actions = actions;
68 self
69 }
70
71 pub fn data(mut self, data: Vec<u8>) -> Self {
73 self.data = data;
74 self
75 }
76
77 pub fn to_message(&self, version: Version, xid: u32) -> Message {
79 let mut buf = BytesMut::new();
80
81 let actions_bytes = self.actions.encode();
83 let actions_len = actions_bytes.len() as u16;
84
85 buf.put_u32(self.buffer_id);
94 buf.put_u32(self.in_port);
95 buf.put_u16(actions_len);
96 buf.put_slice(&[0u8; 6]); buf.extend_from_slice(&actions_bytes);
99
100 if self.buffer_id == OFP_NO_BUFFER {
102 buf.extend_from_slice(&self.data);
103 }
104
105 let total_len = (Header::SIZE + buf.len()) as u16;
106
107 let header = Header {
108 version,
109 msg_type: MessageType::PacketOut,
110 length: total_len,
111 xid,
112 };
113
114 Message {
115 header,
116 body: buf.freeze(),
117 }
118 }
119}
120
121impl Default for PacketOut {
122 fn default() -> Self {
123 Self::new()
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130
131 #[test]
132 fn packet_out_basic() {
133 let pkt = PacketOut::new()
134 .in_port(1)
135 .actions(ActionList::new().output(2))
136 .data(vec![0x00, 0x01, 0x02, 0x03]);
137
138 let msg = pkt.to_message(Version::Of13, 42);
139 assert_eq!(msg.header.msg_type, MessageType::PacketOut);
140 assert_eq!(msg.header.xid, 42);
141 }
142
143 #[test]
144 fn packet_out_from_buffer() {
145 let pkt = PacketOut::from_buffer(123)
146 .in_port(5)
147 .actions(ActionList::new().output(10));
148
149 assert_eq!(pkt.buffer_id, 123);
150 assert_eq!(pkt.in_port, 5);
151 }
152}