rtnetlink/traffic_control/
get.rs

1// SPDX-License-Identifier: MIT
2
3use futures_util::{
4    future::{self, Either},
5    stream::{Stream, StreamExt},
6    FutureExt,
7};
8use netlink_packet_core::{NetlinkMessage, NLM_F_DUMP, NLM_F_REQUEST};
9use netlink_packet_route::{
10    tc::{TcHandle, TcMessage},
11    RouteNetlinkMessage,
12};
13
14use crate::{try_rtnl, Error, Handle};
15
16#[derive(Debug, Clone)]
17pub struct QDiscGetRequest {
18    handle: Handle,
19    message: TcMessage,
20}
21
22impl QDiscGetRequest {
23    pub(crate) fn new(handle: Handle) -> Self {
24        QDiscGetRequest {
25            handle,
26            message: TcMessage::default(),
27        }
28    }
29
30    /// Execute the request
31    pub fn execute(self) -> impl Stream<Item = Result<TcMessage, Error>> {
32        let QDiscGetRequest {
33            mut handle,
34            message,
35        } = self;
36
37        let mut req = NetlinkMessage::from(
38            RouteNetlinkMessage::GetQueueDiscipline(message),
39        );
40        req.header.flags = NLM_F_REQUEST | NLM_F_DUMP;
41
42        match handle.request(req) {
43            Ok(response) => Either::Left(response.map(move |msg| {
44                Ok(try_rtnl!(msg, RouteNetlinkMessage::NewQueueDiscipline))
45            })),
46            Err(e) => {
47                Either::Right(future::err::<TcMessage, Error>(e).into_stream())
48            }
49        }
50    }
51
52    pub fn index(mut self, index: i32) -> Self {
53        self.message.header.index = index;
54        self
55    }
56
57    /// Get ingress qdisc
58    pub fn ingress(mut self) -> Self {
59        self.message.header.parent = TcHandle::INGRESS;
60        self
61    }
62}
63
64#[derive(Debug, Clone)]
65pub struct TrafficClassGetRequest {
66    handle: Handle,
67    message: TcMessage,
68}
69
70impl TrafficClassGetRequest {
71    pub(crate) fn new(handle: Handle, ifindex: i32) -> Self {
72        let mut message = TcMessage::default();
73        message.header.index = ifindex;
74        TrafficClassGetRequest { handle, message }
75    }
76
77    /// Execute the request
78    pub fn execute(self) -> impl Stream<Item = Result<TcMessage, Error>> {
79        let TrafficClassGetRequest {
80            mut handle,
81            message,
82        } = self;
83
84        let mut req =
85            NetlinkMessage::from(RouteNetlinkMessage::GetTrafficClass(message));
86        req.header.flags = NLM_F_REQUEST | NLM_F_DUMP;
87
88        match handle.request(req) {
89            Ok(response) => Either::Left(response.map(move |msg| {
90                Ok(try_rtnl!(msg, RouteNetlinkMessage::NewTrafficClass))
91            })),
92            Err(e) => {
93                Either::Right(future::err::<TcMessage, Error>(e).into_stream())
94            }
95        }
96    }
97}
98
99#[derive(Debug, Clone)]
100pub struct TrafficFilterGetRequest {
101    handle: Handle,
102    message: TcMessage,
103}
104
105impl TrafficFilterGetRequest {
106    pub(crate) fn new(handle: Handle, ifindex: i32) -> Self {
107        let mut message = TcMessage::default();
108        message.header.index = ifindex;
109        TrafficFilterGetRequest { handle, message }
110    }
111
112    /// Execute the request
113    pub fn execute(self) -> impl Stream<Item = Result<TcMessage, Error>> {
114        let TrafficFilterGetRequest {
115            mut handle,
116            message,
117        } = self;
118
119        let mut req = NetlinkMessage::from(
120            RouteNetlinkMessage::GetTrafficFilter(message),
121        );
122        req.header.flags = NLM_F_REQUEST | NLM_F_DUMP;
123
124        match handle.request(req) {
125            Ok(response) => Either::Left(response.map(move |msg| {
126                Ok(try_rtnl!(msg, RouteNetlinkMessage::NewTrafficFilter))
127            })),
128            Err(e) => {
129                Either::Right(future::err::<TcMessage, Error>(e).into_stream())
130            }
131        }
132    }
133
134    /// Set parent to root.
135    pub fn root(mut self) -> Self {
136        self.message.header.parent = TcHandle::ROOT;
137        self
138    }
139
140    /// Set parent to ingress.
141    pub fn ingress(mut self) -> Self {
142        self.message.header.parent = TcHandle {
143            major: 0xffff,
144            minor: TcHandle::MIN_INGRESS,
145        };
146        self
147    }
148
149    /// Set parent to egress.
150    pub fn egress(mut self) -> Self {
151        self.message.header.parent = TcHandle {
152            major: 0xffff,
153            minor: TcHandle::MIN_EGRESS,
154        };
155        self
156    }
157}
158
159#[derive(Debug, Clone)]
160pub struct TrafficChainGetRequest {
161    handle: Handle,
162    message: TcMessage,
163}
164
165impl TrafficChainGetRequest {
166    pub(crate) fn new(handle: Handle, ifindex: i32) -> Self {
167        let mut message = TcMessage::default();
168        message.header.index = ifindex;
169        TrafficChainGetRequest { handle, message }
170    }
171
172    /// Execute the request
173    pub fn execute(self) -> impl Stream<Item = Result<TcMessage, Error>> {
174        let TrafficChainGetRequest {
175            mut handle,
176            message,
177        } = self;
178
179        let mut req =
180            NetlinkMessage::from(RouteNetlinkMessage::GetTrafficChain(message));
181        req.header.flags = NLM_F_REQUEST | NLM_F_DUMP;
182
183        match handle.request(req) {
184            Ok(response) => Either::Left(response.map(move |msg| {
185                Ok(try_rtnl!(msg, RouteNetlinkMessage::NewTrafficChain))
186            })),
187            Err(e) => {
188                Either::Right(future::err::<TcMessage, Error>(e).into_stream())
189            }
190        }
191    }
192}