1use std::collections::HashMap;
11use std::io::{BufRead, BufReader, Write};
12use std::path::PathBuf;
13
14use crate::error::ErrorKind::*;
15use crate::error::*;
16
17use crate::read_u64_from;
18use crate::{
19 ControllIdentifier, ControllerInternal, Controllers, NetworkResources, Resources, Subsystem,
20};
21
22#[derive(Debug, Clone)]
28pub struct NetPrioController {
29 base: PathBuf,
30 path: PathBuf,
31}
32
33impl ControllerInternal for NetPrioController {
34 fn control_type(&self) -> Controllers {
35 Controllers::NetPrio
36 }
37 fn get_path(&self) -> &PathBuf {
38 &self.path
39 }
40 fn get_path_mut(&mut self) -> &mut PathBuf {
41 &mut self.path
42 }
43 fn get_base(&self) -> &PathBuf {
44 &self.base
45 }
46
47 fn apply(&self, res: &Resources) -> Result<()> {
48 let res: &NetworkResources = &res.network;
50
51 for i in &res.priorities {
52 let _ = self.set_if_prio(&i.name, i.priority);
53 }
54
55 Ok(())
56 }
57}
58
59impl ControllIdentifier for NetPrioController {
60 fn controller_type() -> Controllers {
61 Controllers::NetPrio
62 }
63}
64
65impl<'a> From<&'a Subsystem> for &'a NetPrioController {
66 fn from(sub: &'a Subsystem) -> &'a NetPrioController {
67 unsafe {
68 match sub {
69 Subsystem::NetPrio(c) => c,
70 _ => {
71 assert_eq!(1, 0);
72 let v = std::mem::MaybeUninit::uninit();
73 v.assume_init()
74 }
75 }
76 }
77 }
78}
79
80impl NetPrioController {
81 pub fn new(root: PathBuf) -> Self {
83 Self {
84 base: root.clone(),
85 path: root,
86 }
87 }
88
89 pub fn prio_idx(&self) -> u64 {
91 self.open_path("net_prio.prioidx", false)
92 .and_then(read_u64_from)
93 .unwrap_or(0)
94 }
95
96 #[allow(clippy::iter_nth_zero, clippy::unnecessary_unwrap)]
98 pub fn ifpriomap(&self) -> Result<HashMap<String, u64>> {
99 self.open_path("net_prio.ifpriomap", false)
100 .and_then(|file| {
101 let bf = BufReader::new(file);
102 bf.lines().fold(Ok(HashMap::new()), |acc, line| {
103 if acc.is_err() {
104 acc
105 } else {
106 let mut acc = acc.unwrap();
107 let l = line.unwrap();
108 let mut sp = l.split_whitespace();
109
110 let ifname = sp.nth(0);
111 let ifprio = sp.nth(1);
112 if ifname.is_none() || ifprio.is_none() {
113 Err(Error::new(ParseError))
114 } else {
115 let ifname = ifname.unwrap();
116 let ifprio = ifprio.unwrap().trim().parse();
117 match ifprio {
118 Err(e) => Err(Error::with_cause(ParseError, e)),
119 Ok(_) => {
120 acc.insert(ifname.to_string(), ifprio.unwrap());
121 Ok(acc)
122 }
123 }
124 }
125 }
126 })
127 })
128 }
129
130 pub fn set_if_prio(&self, eif: &str, prio: u64) -> Result<()> {
132 self.open_path("net_prio.ifpriomap", true)
133 .and_then(|mut file| {
134 file.write_all(format!("{} {}", eif, prio).as_ref())
135 .map_err(|e| {
136 Error::with_cause(
137 WriteFailed(
138 "net_prio.ifpriomap".to_string(),
139 format!("{} {}", eif, prio),
140 ),
141 e,
142 )
143 })
144 })
145 }
146}