Skip to main content

rovs_openflow/
message.rs

1//! OpenFlow message types.
2
3use bytes::{Buf, BufMut, Bytes, BytesMut};
4
5use crate::{Error, Result, Version};
6
7/// OpenFlow message header (8 bytes).
8#[derive(Debug, Clone, Copy)]
9pub struct Header {
10    /// Protocol version
11    pub version: Version,
12    /// Message type
13    pub msg_type: MessageType,
14    /// Total message length (including header)
15    pub length: u16,
16    /// Transaction ID
17    pub xid: u32,
18}
19
20impl Header {
21    /// Header size in bytes.
22    pub const SIZE: usize = 8;
23
24    /// Encode the header to bytes.
25    pub fn encode(&self, buf: &mut BytesMut) {
26        buf.put_u8(self.version.wire_version());
27        buf.put_u8(self.msg_type as u8);
28        buf.put_u16(self.length);
29        buf.put_u32(self.xid);
30    }
31
32    /// Decode a header from bytes.
33    pub fn decode(buf: &mut Bytes) -> Result<Self> {
34        if buf.remaining() < Self::SIZE {
35            return Err(Error::Parse("header too short".into()));
36        }
37
38        let version = Version::try_from(buf.get_u8())?;
39        let msg_type = MessageType::try_from(buf.get_u8())?;
40        let length = buf.get_u16();
41        let xid = buf.get_u32();
42
43        Ok(Self {
44            version,
45            msg_type,
46            length,
47            xid,
48        })
49    }
50}
51
52/// OpenFlow message types.
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54#[repr(u8)]
55pub enum MessageType {
56    // Symmetric messages
57    /// Hello message
58    Hello = 0,
59    /// Error message
60    Error = 1,
61    /// Echo request
62    EchoRequest = 2,
63    /// Echo reply
64    EchoReply = 3,
65    /// Experimenter message
66    Experimenter = 4,
67
68    // Controller-to-switch messages
69    /// Features request
70    FeaturesRequest = 5,
71    /// Features reply
72    FeaturesReply = 6,
73    /// Get config request
74    GetConfigRequest = 7,
75    /// Get config reply
76    GetConfigReply = 8,
77    /// Set config
78    SetConfig = 9,
79
80    // Async messages
81    /// Packet in
82    PacketIn = 10,
83    /// Flow removed
84    FlowRemoved = 11,
85    /// Port status
86    PortStatus = 12,
87
88    // Controller-to-switch messages
89    /// Packet out
90    PacketOut = 13,
91    /// Flow mod
92    FlowMod = 14,
93    /// Group mod (OF 1.1+)
94    GroupMod = 15,
95    /// Port mod
96    PortMod = 16,
97    /// Table mod (OF 1.1+)
98    TableMod = 17,
99
100    // Multipart messages (OF 1.3+)
101    /// Multipart request
102    MultipartRequest = 18,
103    /// Multipart reply
104    MultipartReply = 19,
105
106    // Barrier
107    /// Barrier request
108    BarrierRequest = 20,
109    /// Barrier reply
110    BarrierReply = 21,
111
112    // Controller role (OF 1.2+)
113    /// Role request
114    RoleRequest = 24,
115    /// Role reply
116    RoleReply = 25,
117
118    // Async config (OF 1.3+)
119    /// Get async request
120    GetAsyncRequest = 26,
121    /// Get async reply
122    GetAsyncReply = 27,
123    /// Set async
124    SetAsync = 28,
125
126    // Meters (OF 1.3+)
127    /// Meter mod
128    MeterMod = 29,
129
130    // Bundle (OF 1.4+)
131    /// Bundle control
132    BundleControl = 33,
133    /// Bundle add message
134    BundleAddMessage = 34,
135}
136
137impl TryFrom<u8> for MessageType {
138    type Error = Error;
139
140    fn try_from(v: u8) -> Result<Self> {
141        match v {
142            0 => Ok(Self::Hello),
143            1 => Ok(Self::Error),
144            2 => Ok(Self::EchoRequest),
145            3 => Ok(Self::EchoReply),
146            4 => Ok(Self::Experimenter),
147            5 => Ok(Self::FeaturesRequest),
148            6 => Ok(Self::FeaturesReply),
149            7 => Ok(Self::GetConfigRequest),
150            8 => Ok(Self::GetConfigReply),
151            9 => Ok(Self::SetConfig),
152            10 => Ok(Self::PacketIn),
153            11 => Ok(Self::FlowRemoved),
154            12 => Ok(Self::PortStatus),
155            13 => Ok(Self::PacketOut),
156            14 => Ok(Self::FlowMod),
157            15 => Ok(Self::GroupMod),
158            16 => Ok(Self::PortMod),
159            17 => Ok(Self::TableMod),
160            18 => Ok(Self::MultipartRequest),
161            19 => Ok(Self::MultipartReply),
162            20 => Ok(Self::BarrierRequest),
163            21 => Ok(Self::BarrierReply),
164            24 => Ok(Self::RoleRequest),
165            25 => Ok(Self::RoleReply),
166            26 => Ok(Self::GetAsyncRequest),
167            27 => Ok(Self::GetAsyncReply),
168            28 => Ok(Self::SetAsync),
169            29 => Ok(Self::MeterMod),
170            33 => Ok(Self::BundleControl),
171            34 => Ok(Self::BundleAddMessage),
172            _ => Err(Error::InvalidMessage(format!("unknown message type: {v}"))),
173        }
174    }
175}
176
177/// A complete OpenFlow message.
178#[derive(Debug)]
179pub struct Message {
180    /// Message header
181    pub header: Header,
182    /// Message body
183    pub body: Bytes,
184}
185
186impl Message {
187    /// Create a new message.
188    pub fn new(version: Version, msg_type: MessageType, xid: u32, body: Bytes) -> Self {
189        let length = (Header::SIZE + body.len()) as u16;
190        Self {
191            header: Header {
192                version,
193                msg_type,
194                length,
195                xid,
196            },
197            body,
198        }
199    }
200
201    /// Encode the message to bytes.
202    pub fn encode(&self) -> BytesMut {
203        let mut buf = BytesMut::with_capacity(self.header.length as usize);
204        self.header.encode(&mut buf);
205        buf.extend_from_slice(&self.body);
206        buf
207    }
208}