1#![doc = "OVS packet execution over generic netlink.\n\nOnly OVS_PACKET_CMD_EXECUTE is exposed as a genl operation.\nOVS_PACKET_CMD_MISS and OVS_PACKET_CMD_ACTION are kernel-to-userspace\nupcalls sent via genlmsg_unicast() to the vport\\'s upcall_pid and have\nno associated genl_ops or multicast group.\n\nSeveral attributes in the attribute set (userdata, egress-tun-key, len)\nexist for the upcall path and are not used by the EXECUTE operation. For\nEXECUTE, packet, key, and actions are mandatory (kernel returns -EINVAL\nwithout them).\n"]
2#![allow(clippy::all)]
3#![allow(unused_imports)]
4#![allow(unused_assignments)]
5#![allow(non_snake_case)]
6#![allow(unused_variables)]
7#![allow(irrefutable_let_patterns)]
8#![allow(unreachable_code)]
9#![allow(unreachable_patterns)]
10use crate::builtin::{BuiltinBitfield32, BuiltinNfgenmsg, Nlmsghdr, PushDummy};
11use crate::{
12 consts,
13 traits::{NetlinkRequest, Protocol},
14 utils::*,
15};
16pub const PROTONAME: &str = "ovs_packet";
17pub const PROTONAME_CSTR: &CStr = c"ovs_packet";
18#[derive(Debug)]
19#[repr(C, packed(4))]
20pub struct OvsHeader {
21 pub dp_ifindex: u32,
22}
23impl Clone for OvsHeader {
24 fn clone(&self) -> Self {
25 Self::new_from_array(*self.as_array())
26 }
27}
28#[doc = "Create zero-initialized struct"]
29impl Default for OvsHeader {
30 fn default() -> Self {
31 Self::new()
32 }
33}
34impl OvsHeader {
35 #[doc = "Create zero-initialized struct"]
36 pub fn new() -> Self {
37 Self::new_from_array([0u8; Self::len()])
38 }
39 #[doc = "Copy from contents from slice"]
40 pub fn new_from_slice(other: &[u8]) -> Option<Self> {
41 if other.len() != Self::len() {
42 return None;
43 }
44 let mut buf = [0u8; Self::len()];
45 buf.clone_from_slice(other);
46 Some(Self::new_from_array(buf))
47 }
48 #[doc = "Copy from contents from another slice, padding with zeros or truncating when needed"]
49 pub fn new_from_zeroed(other: &[u8]) -> Self {
50 let mut buf = [0u8; Self::len()];
51 let len = buf.len().min(other.len());
52 buf[..len].clone_from_slice(&other[..len]);
53 Self::new_from_array(buf)
54 }
55 pub fn new_from_array(buf: [u8; 4usize]) -> Self {
56 unsafe { std::mem::transmute(buf) }
57 }
58 pub fn as_slice(&self) -> &[u8] {
59 unsafe {
60 let ptr: *const u8 = std::mem::transmute(self as *const Self);
61 std::slice::from_raw_parts(ptr, Self::len())
62 }
63 }
64 pub fn from_slice(buf: &[u8]) -> &Self {
65 assert!(buf.len() >= Self::len());
66 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
67 unsafe { std::mem::transmute(buf.as_ptr()) }
68 }
69 pub fn as_array(&self) -> &[u8; 4usize] {
70 unsafe { std::mem::transmute(self) }
71 }
72 pub fn from_array(buf: &[u8; 4usize]) -> &Self {
73 assert!(buf.as_ptr() as usize % std::mem::align_of::<Self>() == 0);
74 unsafe { std::mem::transmute(buf) }
75 }
76 pub fn into_array(self) -> [u8; 4usize] {
77 unsafe { std::mem::transmute(self) }
78 }
79 pub const fn len() -> usize {
80 const _: () = assert!(std::mem::size_of::<OvsHeader>() == 4usize);
81 4usize
82 }
83}
84#[derive(Clone)]
85pub enum Packet<'a> {
86 #[doc = "Packet data, from the start of the Ethernet header.\n"]
87 Packet(&'a [u8]),
88 #[doc = "Nested [OVS_KEY_ATTR]()\\* attributes, extracted flow key. Defined as\nbinary because the key attribute-set belongs to the ovs_flow family\nspec; cross-spec references are not supported.\n"]
89 Key(&'a [u8]),
90 #[doc = "Nested [OVS_ACTION_ATTR]()\\* attributes. Defined as binary for the same\nreason as key.\n"]
91 Actions(&'a [u8]),
92 #[doc = "Opaque userspace cookie from OVS_USERSPACE_ATTR_USERDATA.\n"]
93 Userdata(&'a [u8]),
94 #[doc = "Nested [OVS_TUNNEL_KEY_ATTR]()\\* for output tunnel metadata.\n"]
95 EgressTunKey(&'a [u8]),
96 #[doc = "Packet operation is a feature probe, error logging suppressed.\n"]
97 Probe(()),
98 #[doc = "Maximum received IP fragment size.\n"]
99 Mru(u16),
100 #[doc = "Packet size before truncation.\n"]
101 Len(u32),
102 #[doc = "Packet hash, low 32 bits are skb hash, upper bits are flags.\n"]
103 Hash(u64),
104 #[doc = "Netlink PID to use for upcalls during EXECUTE processing.\n"]
105 UpcallPid(u32),
106}
107impl<'a> IterablePacket<'a> {
108 #[doc = "Packet data, from the start of the Ethernet header.\n"]
109 pub fn get_packet(&self) -> Result<&'a [u8], ErrorContext> {
110 let mut iter = self.clone();
111 iter.pos = 0;
112 for attr in iter {
113 if let Ok(Packet::Packet(val)) = attr {
114 return Ok(val);
115 }
116 }
117 Err(ErrorContext::new_missing(
118 "Packet",
119 "Packet",
120 self.orig_loc,
121 self.buf.as_ptr() as usize,
122 ))
123 }
124 #[doc = "Nested [OVS_KEY_ATTR]()\\* attributes, extracted flow key. Defined as\nbinary because the key attribute-set belongs to the ovs_flow family\nspec; cross-spec references are not supported.\n"]
125 pub fn get_key(&self) -> Result<&'a [u8], ErrorContext> {
126 let mut iter = self.clone();
127 iter.pos = 0;
128 for attr in iter {
129 if let Ok(Packet::Key(val)) = attr {
130 return Ok(val);
131 }
132 }
133 Err(ErrorContext::new_missing(
134 "Packet",
135 "Key",
136 self.orig_loc,
137 self.buf.as_ptr() as usize,
138 ))
139 }
140 #[doc = "Nested [OVS_ACTION_ATTR]()\\* attributes. Defined as binary for the same\nreason as key.\n"]
141 pub fn get_actions(&self) -> Result<&'a [u8], ErrorContext> {
142 let mut iter = self.clone();
143 iter.pos = 0;
144 for attr in iter {
145 if let Ok(Packet::Actions(val)) = attr {
146 return Ok(val);
147 }
148 }
149 Err(ErrorContext::new_missing(
150 "Packet",
151 "Actions",
152 self.orig_loc,
153 self.buf.as_ptr() as usize,
154 ))
155 }
156 #[doc = "Opaque userspace cookie from OVS_USERSPACE_ATTR_USERDATA.\n"]
157 pub fn get_userdata(&self) -> Result<&'a [u8], ErrorContext> {
158 let mut iter = self.clone();
159 iter.pos = 0;
160 for attr in iter {
161 if let Ok(Packet::Userdata(val)) = attr {
162 return Ok(val);
163 }
164 }
165 Err(ErrorContext::new_missing(
166 "Packet",
167 "Userdata",
168 self.orig_loc,
169 self.buf.as_ptr() as usize,
170 ))
171 }
172 #[doc = "Nested [OVS_TUNNEL_KEY_ATTR]()\\* for output tunnel metadata.\n"]
173 pub fn get_egress_tun_key(&self) -> Result<&'a [u8], ErrorContext> {
174 let mut iter = self.clone();
175 iter.pos = 0;
176 for attr in iter {
177 if let Ok(Packet::EgressTunKey(val)) = attr {
178 return Ok(val);
179 }
180 }
181 Err(ErrorContext::new_missing(
182 "Packet",
183 "EgressTunKey",
184 self.orig_loc,
185 self.buf.as_ptr() as usize,
186 ))
187 }
188 #[doc = "Packet operation is a feature probe, error logging suppressed.\n"]
189 pub fn get_probe(&self) -> Result<(), ErrorContext> {
190 let mut iter = self.clone();
191 iter.pos = 0;
192 for attr in iter {
193 if let Ok(Packet::Probe(val)) = attr {
194 return Ok(val);
195 }
196 }
197 Err(ErrorContext::new_missing(
198 "Packet",
199 "Probe",
200 self.orig_loc,
201 self.buf.as_ptr() as usize,
202 ))
203 }
204 #[doc = "Maximum received IP fragment size.\n"]
205 pub fn get_mru(&self) -> Result<u16, ErrorContext> {
206 let mut iter = self.clone();
207 iter.pos = 0;
208 for attr in iter {
209 if let Ok(Packet::Mru(val)) = attr {
210 return Ok(val);
211 }
212 }
213 Err(ErrorContext::new_missing(
214 "Packet",
215 "Mru",
216 self.orig_loc,
217 self.buf.as_ptr() as usize,
218 ))
219 }
220 #[doc = "Packet size before truncation.\n"]
221 pub fn get_len(&self) -> Result<u32, ErrorContext> {
222 let mut iter = self.clone();
223 iter.pos = 0;
224 for attr in iter {
225 if let Ok(Packet::Len(val)) = attr {
226 return Ok(val);
227 }
228 }
229 Err(ErrorContext::new_missing(
230 "Packet",
231 "Len",
232 self.orig_loc,
233 self.buf.as_ptr() as usize,
234 ))
235 }
236 #[doc = "Packet hash, low 32 bits are skb hash, upper bits are flags.\n"]
237 pub fn get_hash(&self) -> Result<u64, ErrorContext> {
238 let mut iter = self.clone();
239 iter.pos = 0;
240 for attr in iter {
241 if let Ok(Packet::Hash(val)) = attr {
242 return Ok(val);
243 }
244 }
245 Err(ErrorContext::new_missing(
246 "Packet",
247 "Hash",
248 self.orig_loc,
249 self.buf.as_ptr() as usize,
250 ))
251 }
252 #[doc = "Netlink PID to use for upcalls during EXECUTE processing.\n"]
253 pub fn get_upcall_pid(&self) -> Result<u32, ErrorContext> {
254 let mut iter = self.clone();
255 iter.pos = 0;
256 for attr in iter {
257 if let Ok(Packet::UpcallPid(val)) = attr {
258 return Ok(val);
259 }
260 }
261 Err(ErrorContext::new_missing(
262 "Packet",
263 "UpcallPid",
264 self.orig_loc,
265 self.buf.as_ptr() as usize,
266 ))
267 }
268}
269impl Packet<'_> {
270 pub fn new<'a>(buf: &'a [u8]) -> IterablePacket<'a> {
271 IterablePacket::with_loc(buf, buf.as_ptr() as usize)
272 }
273 fn attr_from_type(r#type: u16) -> Option<&'static str> {
274 let res = match r#type {
275 1u16 => "Packet",
276 2u16 => "Key",
277 3u16 => "Actions",
278 4u16 => "Userdata",
279 5u16 => "EgressTunKey",
280 6u16 => "Unused1",
281 7u16 => "Unused2",
282 8u16 => "Probe",
283 9u16 => "Mru",
284 10u16 => "Len",
285 11u16 => "Hash",
286 12u16 => "UpcallPid",
287 _ => return None,
288 };
289 Some(res)
290 }
291}
292#[derive(Clone, Copy, Default)]
293pub struct IterablePacket<'a> {
294 buf: &'a [u8],
295 pos: usize,
296 orig_loc: usize,
297}
298impl<'a> IterablePacket<'a> {
299 fn with_loc(buf: &'a [u8], orig_loc: usize) -> Self {
300 Self {
301 buf,
302 pos: 0,
303 orig_loc,
304 }
305 }
306 pub fn get_buf(&self) -> &'a [u8] {
307 self.buf
308 }
309}
310impl<'a> Iterator for IterablePacket<'a> {
311 type Item = Result<Packet<'a>, ErrorContext>;
312 fn next(&mut self) -> Option<Self::Item> {
313 let mut pos;
314 let mut r#type;
315 loop {
316 pos = self.pos;
317 r#type = None;
318 if self.buf.len() == self.pos {
319 return None;
320 }
321 let Some((header, next)) = chop_header(self.buf, &mut self.pos) else {
322 self.pos = self.buf.len();
323 break;
324 };
325 r#type = Some(header.r#type);
326 let res = match header.r#type {
327 1u16 => Packet::Packet({
328 let res = Some(next);
329 let Some(val) = res else { break };
330 val
331 }),
332 2u16 => Packet::Key({
333 let res = Some(next);
334 let Some(val) = res else { break };
335 val
336 }),
337 3u16 => Packet::Actions({
338 let res = Some(next);
339 let Some(val) = res else { break };
340 val
341 }),
342 4u16 => Packet::Userdata({
343 let res = Some(next);
344 let Some(val) = res else { break };
345 val
346 }),
347 5u16 => Packet::EgressTunKey({
348 let res = Some(next);
349 let Some(val) = res else { break };
350 val
351 }),
352 8u16 => Packet::Probe(()),
353 9u16 => Packet::Mru({
354 let res = parse_u16(next);
355 let Some(val) = res else { break };
356 val
357 }),
358 10u16 => Packet::Len({
359 let res = parse_u32(next);
360 let Some(val) = res else { break };
361 val
362 }),
363 11u16 => Packet::Hash({
364 let res = parse_u64(next);
365 let Some(val) = res else { break };
366 val
367 }),
368 12u16 => Packet::UpcallPid({
369 let res = parse_u32(next);
370 let Some(val) = res else { break };
371 val
372 }),
373 n if cfg!(any(test, feature = "deny-unknown-attrs")) => break,
374 n => continue,
375 };
376 return Some(Ok(res));
377 }
378 Some(Err(ErrorContext::new(
379 "Packet",
380 r#type.and_then(|t| Packet::attr_from_type(t)),
381 self.orig_loc,
382 self.buf.as_ptr().wrapping_add(pos) as usize,
383 )))
384 }
385}
386impl<'a> std::fmt::Debug for IterablePacket<'_> {
387 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
388 let mut fmt = f.debug_struct("Packet");
389 for attr in self.clone() {
390 let attr = match attr {
391 Ok(a) => a,
392 Err(err) => {
393 fmt.finish()?;
394 f.write_str("Err(")?;
395 err.fmt(f)?;
396 return f.write_str(")");
397 }
398 };
399 match attr {
400 Packet::Packet(val) => fmt.field("Packet", &val),
401 Packet::Key(val) => fmt.field("Key", &val),
402 Packet::Actions(val) => fmt.field("Actions", &val),
403 Packet::Userdata(val) => fmt.field("Userdata", &val),
404 Packet::EgressTunKey(val) => fmt.field("EgressTunKey", &val),
405 Packet::Probe(val) => fmt.field("Probe", &val),
406 Packet::Mru(val) => fmt.field("Mru", &val),
407 Packet::Len(val) => fmt.field("Len", &val),
408 Packet::Hash(val) => fmt.field("Hash", &val),
409 Packet::UpcallPid(val) => fmt.field("UpcallPid", &val),
410 };
411 }
412 fmt.finish()
413 }
414}
415impl IterablePacket<'_> {
416 pub fn lookup_attr(
417 &self,
418 offset: usize,
419 missing_type: Option<u16>,
420 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
421 let mut stack = Vec::new();
422 let cur = ErrorContext::calc_offset(self.orig_loc, self.buf.as_ptr() as usize);
423 if missing_type.is_some() && cur == offset {
424 stack.push(("Packet", offset));
425 return (stack, missing_type.and_then(|t| Packet::attr_from_type(t)));
426 }
427 if cur > offset || cur + self.buf.len() < offset {
428 return (stack, None);
429 }
430 let mut attrs = self.clone();
431 let mut last_off = cur + attrs.pos;
432 while let Some(attr) = attrs.next() {
433 let Ok(attr) = attr else { break };
434 match attr {
435 Packet::Packet(val) => {
436 if last_off == offset {
437 stack.push(("Packet", last_off));
438 break;
439 }
440 }
441 Packet::Key(val) => {
442 if last_off == offset {
443 stack.push(("Key", last_off));
444 break;
445 }
446 }
447 Packet::Actions(val) => {
448 if last_off == offset {
449 stack.push(("Actions", last_off));
450 break;
451 }
452 }
453 Packet::Userdata(val) => {
454 if last_off == offset {
455 stack.push(("Userdata", last_off));
456 break;
457 }
458 }
459 Packet::EgressTunKey(val) => {
460 if last_off == offset {
461 stack.push(("EgressTunKey", last_off));
462 break;
463 }
464 }
465 Packet::Probe(val) => {
466 if last_off == offset {
467 stack.push(("Probe", last_off));
468 break;
469 }
470 }
471 Packet::Mru(val) => {
472 if last_off == offset {
473 stack.push(("Mru", last_off));
474 break;
475 }
476 }
477 Packet::Len(val) => {
478 if last_off == offset {
479 stack.push(("Len", last_off));
480 break;
481 }
482 }
483 Packet::Hash(val) => {
484 if last_off == offset {
485 stack.push(("Hash", last_off));
486 break;
487 }
488 }
489 Packet::UpcallPid(val) => {
490 if last_off == offset {
491 stack.push(("UpcallPid", last_off));
492 break;
493 }
494 }
495 _ => {}
496 };
497 last_off = cur + attrs.pos;
498 }
499 if !stack.is_empty() {
500 stack.push(("Packet", cur));
501 }
502 (stack, None)
503 }
504}
505pub struct PushPacket<Prev: Rec> {
506 pub(crate) prev: Option<Prev>,
507 pub(crate) header_offset: Option<usize>,
508}
509impl<Prev: Rec> Rec for PushPacket<Prev> {
510 fn as_rec_mut(&mut self) -> &mut Vec<u8> {
511 self.prev.as_mut().unwrap().as_rec_mut()
512 }
513 fn as_rec(&self) -> &Vec<u8> {
514 self.prev.as_ref().unwrap().as_rec()
515 }
516}
517impl<Prev: Rec> PushPacket<Prev> {
518 pub fn new(prev: Prev) -> Self {
519 Self {
520 prev: Some(prev),
521 header_offset: None,
522 }
523 }
524 pub fn end_nested(mut self) -> Prev {
525 let mut prev = self.prev.take().unwrap();
526 if let Some(header_offset) = &self.header_offset {
527 finalize_nested_header(prev.as_rec_mut(), *header_offset);
528 }
529 prev
530 }
531 #[doc = "Packet data, from the start of the Ethernet header.\n"]
532 pub fn push_packet(mut self, value: &[u8]) -> Self {
533 push_header(self.as_rec_mut(), 1u16, value.len() as u16);
534 self.as_rec_mut().extend(value);
535 self
536 }
537 #[doc = "Nested [OVS_KEY_ATTR]()\\* attributes, extracted flow key. Defined as\nbinary because the key attribute-set belongs to the ovs_flow family\nspec; cross-spec references are not supported.\n"]
538 pub fn push_key(mut self, value: &[u8]) -> Self {
539 push_header(self.as_rec_mut(), 2u16, value.len() as u16);
540 self.as_rec_mut().extend(value);
541 self
542 }
543 #[doc = "Nested [OVS_ACTION_ATTR]()\\* attributes. Defined as binary for the same\nreason as key.\n"]
544 pub fn push_actions(mut self, value: &[u8]) -> Self {
545 push_header(self.as_rec_mut(), 3u16, value.len() as u16);
546 self.as_rec_mut().extend(value);
547 self
548 }
549 #[doc = "Opaque userspace cookie from OVS_USERSPACE_ATTR_USERDATA.\n"]
550 pub fn push_userdata(mut self, value: &[u8]) -> Self {
551 push_header(self.as_rec_mut(), 4u16, value.len() as u16);
552 self.as_rec_mut().extend(value);
553 self
554 }
555 #[doc = "Nested [OVS_TUNNEL_KEY_ATTR]()\\* for output tunnel metadata.\n"]
556 pub fn push_egress_tun_key(mut self, value: &[u8]) -> Self {
557 push_header(self.as_rec_mut(), 5u16, value.len() as u16);
558 self.as_rec_mut().extend(value);
559 self
560 }
561 #[doc = "Packet operation is a feature probe, error logging suppressed.\n"]
562 pub fn push_probe(mut self, value: ()) -> Self {
563 push_header(self.as_rec_mut(), 8u16, 0 as u16);
564 self
565 }
566 #[doc = "Maximum received IP fragment size.\n"]
567 pub fn push_mru(mut self, value: u16) -> Self {
568 push_header(self.as_rec_mut(), 9u16, 2 as u16);
569 self.as_rec_mut().extend(value.to_ne_bytes());
570 self
571 }
572 #[doc = "Packet size before truncation.\n"]
573 pub fn push_len(mut self, value: u32) -> Self {
574 push_header(self.as_rec_mut(), 10u16, 4 as u16);
575 self.as_rec_mut().extend(value.to_ne_bytes());
576 self
577 }
578 #[doc = "Packet hash, low 32 bits are skb hash, upper bits are flags.\n"]
579 pub fn push_hash(mut self, value: u64) -> Self {
580 push_header(self.as_rec_mut(), 11u16, 8 as u16);
581 self.as_rec_mut().extend(value.to_ne_bytes());
582 self
583 }
584 #[doc = "Netlink PID to use for upcalls during EXECUTE processing.\n"]
585 pub fn push_upcall_pid(mut self, value: u32) -> Self {
586 push_header(self.as_rec_mut(), 12u16, 4 as u16);
587 self.as_rec_mut().extend(value.to_ne_bytes());
588 self
589 }
590}
591impl<Prev: Rec> Drop for PushPacket<Prev> {
592 fn drop(&mut self) {
593 if let Some(prev) = &mut self.prev {
594 if let Some(header_offset) = &self.header_offset {
595 finalize_nested_header(prev.as_rec_mut(), *header_offset);
596 }
597 }
598 }
599}
600#[doc = "Apply actions to a packet.\n\nRequest attributes:\n- [.push_packet()](PushPacket::push_packet)\n- [.push_key()](PushPacket::push_key)\n- [.push_actions()](PushPacket::push_actions)\n- [.push_probe()](PushPacket::push_probe)\n- [.push_mru()](PushPacket::push_mru)\n- [.push_hash()](PushPacket::push_hash)\n- [.push_upcall_pid()](PushPacket::push_upcall_pid)\n\n"]
601#[derive(Debug)]
602pub struct OpExecuteDo<'r> {
603 request: Request<'r>,
604}
605impl<'r> OpExecuteDo<'r> {
606 pub fn new(mut request: Request<'r>, header: &OvsHeader) -> Self {
607 Self::write_header(request.buf_mut(), header);
608 Self { request: request }
609 }
610 pub fn encode_request<'buf>(
611 buf: &'buf mut Vec<u8>,
612 header: &OvsHeader,
613 ) -> PushPacket<&'buf mut Vec<u8>> {
614 Self::write_header(buf, header);
615 PushPacket::new(buf)
616 }
617 pub fn encode(&mut self) -> PushPacket<&mut Vec<u8>> {
618 PushPacket::new(self.request.buf_mut())
619 }
620 pub fn into_encoder(self) -> PushPacket<RequestBuf<'r>> {
621 PushPacket::new(self.request.buf)
622 }
623 pub fn decode_request<'a>(buf: &'a [u8]) -> (OvsHeader, IterablePacket<'a>) {
624 let (header, attrs) = buf.split_at(buf.len().min(OvsHeader::len()));
625 (
626 OvsHeader::new_from_slice(header).unwrap_or_default(),
627 IterablePacket::with_loc(attrs, buf.as_ptr() as usize),
628 )
629 }
630 fn write_header<Prev: Rec>(prev: &mut Prev, header: &OvsHeader) {
631 prev.as_rec_mut().extend(header.as_slice());
632 }
633}
634impl NetlinkRequest for OpExecuteDo<'_> {
635 fn protocol(&self) -> Protocol {
636 Protocol::Generic("ovs_packet".as_bytes())
637 }
638 fn flags(&self) -> u16 {
639 self.request.flags
640 }
641 fn payload(&self) -> &[u8] {
642 self.request.buf()
643 }
644 type ReplyType<'buf> = (OvsHeader, IterablePacket<'buf>);
645 fn decode_reply<'buf>(buf: &'buf [u8]) -> Self::ReplyType<'buf> {
646 Self::decode_request(buf)
647 }
648 fn lookup(
649 buf: &[u8],
650 offset: usize,
651 missing_type: Option<u16>,
652 ) -> (Vec<(&'static str, usize)>, Option<&'static str>) {
653 Self::decode_request(buf)
654 .1
655 .lookup_attr(offset, missing_type)
656 }
657}
658use crate::traits::LookupFn;
659use crate::utils::RequestBuf;
660#[derive(Debug)]
661pub struct Request<'buf> {
662 buf: RequestBuf<'buf>,
663 flags: u16,
664 writeback: Option<&'buf mut Option<RequestInfo>>,
665}
666#[allow(unused)]
667#[derive(Debug, Clone)]
668pub struct RequestInfo {
669 protocol: Protocol,
670 flags: u16,
671 name: &'static str,
672 lookup: LookupFn,
673}
674impl Request<'static> {
675 pub fn new() -> Self {
676 Self::new_from_buf(Vec::new())
677 }
678 pub fn new_from_buf(buf: Vec<u8>) -> Self {
679 Self {
680 flags: 0,
681 buf: RequestBuf::Own(buf),
682 writeback: None,
683 }
684 }
685 pub fn into_buf(self) -> Vec<u8> {
686 match self.buf {
687 RequestBuf::Own(buf) => buf,
688 _ => unreachable!(),
689 }
690 }
691}
692impl<'buf> Request<'buf> {
693 pub fn new_with_buf(buf: &'buf mut Vec<u8>) -> Self {
694 buf.clear();
695 Self::new_extend(buf)
696 }
697 pub fn new_extend(buf: &'buf mut Vec<u8>) -> Self {
698 Self {
699 flags: 0,
700 buf: RequestBuf::Ref(buf),
701 writeback: None,
702 }
703 }
704 fn do_writeback(&mut self, protocol: Protocol, name: &'static str, lookup: LookupFn) {
705 let Some(writeback) = &mut self.writeback else {
706 return;
707 };
708 **writeback = Some(RequestInfo {
709 protocol,
710 flags: self.flags,
711 name,
712 lookup,
713 })
714 }
715 pub fn buf(&self) -> &Vec<u8> {
716 self.buf.buf()
717 }
718 pub fn buf_mut(&mut self) -> &mut Vec<u8> {
719 self.buf.buf_mut()
720 }
721 #[doc = "Set `NLM_F_CREATE` flag"]
722 pub fn set_create(mut self) -> Self {
723 self.flags |= consts::NLM_F_CREATE as u16;
724 self
725 }
726 #[doc = "Set `NLM_F_EXCL` flag"]
727 pub fn set_excl(mut self) -> Self {
728 self.flags |= consts::NLM_F_EXCL as u16;
729 self
730 }
731 #[doc = "Set `NLM_F_REPLACE` flag"]
732 pub fn set_replace(mut self) -> Self {
733 self.flags |= consts::NLM_F_REPLACE as u16;
734 self
735 }
736 #[doc = "Set `NLM_F_CREATE` and `NLM_F_REPLACE` flag"]
737 pub fn set_change(self) -> Self {
738 self.set_create().set_replace()
739 }
740 #[doc = "Set `NLM_F_APPEND` flag"]
741 pub fn set_append(mut self) -> Self {
742 self.flags |= consts::NLM_F_APPEND as u16;
743 self
744 }
745 #[doc = "Set `self.flags |= flags`"]
746 pub fn set_flags(mut self, flags: u16) -> Self {
747 self.flags |= flags;
748 self
749 }
750 #[doc = "Set `self.flags ^= self.flags & flags`"]
751 pub fn unset_flags(mut self, flags: u16) -> Self {
752 self.flags ^= self.flags & flags;
753 self
754 }
755 #[doc = "Apply actions to a packet.\n\nRequest attributes:\n- [.push_packet()](PushPacket::push_packet)\n- [.push_key()](PushPacket::push_key)\n- [.push_actions()](PushPacket::push_actions)\n- [.push_probe()](PushPacket::push_probe)\n- [.push_mru()](PushPacket::push_mru)\n- [.push_hash()](PushPacket::push_hash)\n- [.push_upcall_pid()](PushPacket::push_upcall_pid)\n\n"]
756 pub fn op_execute_do(self, header: &OvsHeader) -> OpExecuteDo<'buf> {
757 let mut res = OpExecuteDo::new(self, header);
758 res.request
759 .do_writeback(res.protocol(), "op-execute-do", OpExecuteDo::lookup);
760 res
761 }
762}
763#[cfg(test)]
764mod generated_tests {
765 use super::*;
766 #[test]
767 fn tests() {
768 let _ = PushPacket::<&mut Vec<u8>>::push_actions;
769 let _ = PushPacket::<&mut Vec<u8>>::push_hash;
770 let _ = PushPacket::<&mut Vec<u8>>::push_key;
771 let _ = PushPacket::<&mut Vec<u8>>::push_mru;
772 let _ = PushPacket::<&mut Vec<u8>>::push_packet;
773 let _ = PushPacket::<&mut Vec<u8>>::push_probe;
774 let _ = PushPacket::<&mut Vec<u8>>::push_upcall_pid;
775 }
776}