1use std::net::{Ipv4Addr, Ipv6Addr};
2use std::path::PathBuf;
3
4use crate::chardev::CharDev;
5use crate::common::OnOff;
6use crate::to_command::ToArg;
7use crate::to_command::ToCommand;
8use bon::Builder;
9use ipnet::{Ipv4Net, Ipv6Net};
10
11#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
12pub struct SMB {
13 dir: PathBuf,
14 smbserver: Option<String>,
15}
16
17#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Default)]
18pub enum TcpUdp {
19 #[default]
20 Tcp,
21 Udp,
22}
23
24#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
25pub enum ScriptOrNot {
26 Script(PathBuf),
27 None,
28}
29
30impl ToCommand for ScriptOrNot {
31 fn to_command(&self) -> Vec<String> {
32 match self {
33 ScriptOrNot::Script(path) => {
34 vec![path.display().to_string()]
35 }
36 ScriptOrNot::None => {
37 vec!["no".to_string()]
38 }
39 }
40 }
41}
42#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
43pub struct HostForward {
44 protocol: Option<TcpUdp>,
45 hostaddr: Option<String>,
46 hostport: u16,
47 guestaddr: Option<String>,
48 guestport: u16,
49}
50
51#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
52pub enum GuestForwardTarget {
53 Device(CharDev),
54 Cmd((String, Vec<String>)),
55}
56#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
57pub struct GuestForward {
58 server: String,
59 port: u16,
60 target: GuestForwardTarget,
61}
62#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
63pub struct User {
64 id: String,
65 ipv4: Option<OnOff>,
66 net: Option<Ipv4Net>,
67 host: Option<Ipv4Addr>,
68 ipv6: Option<OnOff>,
69 ipv6_net: Option<Ipv6Net>,
70 ipv6_host: Option<Ipv6Addr>,
71 restrict: Option<OnOff>,
72 hostname: Option<String>,
73 dhcpstart: Option<Ipv4Addr>,
74 dns: Option<Ipv4Addr>,
75 ipv6_dns: Option<Ipv6Addr>,
76 dnssearch: Option<Vec<String>>,
77 domainname: Option<String>,
78 tftp: Option<PathBuf>,
79 tftp_server_name: Option<String>,
80 bootfile: Option<PathBuf>,
81 smb: Option<SMB>,
82 hostfwd: Option<Vec<HostForward>>,
83 guestfwd: Option<Vec<GuestForward>>,
84}
85
86impl ToCommand for User {
87 fn to_command(&self) -> Vec<String> {
88 let mut args = vec!["user".to_string(), format!("id={}", self.id.to_string())];
89
90 if let Some(ipv4) = &self.ipv4 {
91 args.push(format!("ipv4={}", ipv4.to_arg()));
92 }
93 if let Some(net) = &self.net {
94 args.push(format!("net={}", net));
95 }
96 if let Some(host) = &self.host {
97 args.push(format!("host={}", host));
98 }
99 if let Some(ipv6) = &self.ipv6 {
100 args.push(format!("ipv6={}", ipv6.to_arg()));
101 }
102 if let Some(ipv6_net) = &self.ipv6_net {
103 args.push(format!("ipv6-net={}", ipv6_net));
104 }
105 if let Some(ipv6_host) = &self.ipv6_host {
106 args.push(format!("ipv6-host={}", ipv6_host));
107 }
108 if let Some(restrict) = &self.restrict {
109 args.push(format!("restrict={}", restrict.to_arg()));
110 }
111 if let Some(hostname) = &self.hostname {
112 args.push(format!("hostname={}", hostname));
113 }
114 if let Some(dhcpstart) = &self.dhcpstart {
115 args.push(format!("dhcpstart={}", dhcpstart));
116 }
117 if let Some(dns) = &self.dns {
118 args.push(format!("dns={}", dns));
119 }
120 if let Some(ipv6_dns) = &self.ipv6_dns {
121 args.push(format!("ipv6-dns={}", ipv6_dns));
122 }
123 if let Some(dnssearch) = &self.dnssearch {
124 args.push(format!("dnssearch={}", dnssearch.join(",")));
125 }
126 if let Some(domainname) = &self.domainname {
127 args.push(format!("domainname={}", domainname));
128 }
129 if let Some(tftp) = &self.tftp {
130 args.push(format!("tftp={}", tftp.display()));
131 }
132 if let Some(tftp_server_name) = &self.tftp_server_name {
133 args.push(format!("tftp-server-name={}", tftp_server_name));
134 }
135 if let Some(bootfile) = &self.bootfile {
136 args.push(format!("bootfile={}", bootfile.display()));
137 }
138 if let Some(smb) = &self.smb {
139 args.push(format!("smb={}", smb.dir.display()));
140 if let Some(smbserver) = &smb.smbserver {
141 args.push(format!("smbserver={}", smbserver));
142 }
143 }
144 if let Some(hostfwds) = &self.hostfwd {
145 for hostfwd in hostfwds {
146 let mut subargs = vec![];
147 if let Some(proto) = &hostfwd.protocol {
148 match proto {
149 TcpUdp::Tcp => {
150 subargs.push("tcp".to_string());
151 }
152 TcpUdp::Udp => {
153 subargs.push("udp".to_string());
154 }
155 }
156 }
157 if let Some(hostaddr) = &hostfwd.hostaddr {
158 subargs.push(hostaddr.to_string());
159 }
160 subargs.push(format!("{}-", hostfwd.hostport));
161 if let Some(guestaddr) = &hostfwd.guestaddr {
162 subargs.push(guestaddr.to_string());
163 }
164 subargs.push(format!("{}", hostfwd.guestport));
165 args.push(subargs.join(";"));
166 }
167 }
168 if let Some(guestfwds) = &self.guestfwd {
169 for guestfwd in guestfwds {
170 let mut subargs = vec!["tcp".to_string()];
171
172 subargs.push(guestfwd.server.to_string());
173 subargs.push(format!("{}", guestfwd.port));
174
175 match &guestfwd.target {
176 GuestForwardTarget::Device(dev) => {
177 subargs.push(format!("device={}", dev.to_command().join(" ")));
178 }
179 GuestForwardTarget::Cmd((cmd, args)) => {
180 subargs.push(format!("cmd:{} {}", cmd, args.join(" ")));
181 }
182 }
183 args.push(subargs.join(":"));
184 }
185 }
186 vec![args.join(",")]
187 }
188}
189
190#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
191pub struct Tap {
192 id: String,
193 fd: Option<String>,
194 fds: Option<Vec<String>>,
195 ifname: Option<String>,
196 script: Option<ScriptOrNot>,
197 downscript: Option<ScriptOrNot>,
198 br: Option<String>,
199 helper: Option<String>,
200 sndbuf: Option<usize>,
201 vnet_hdr: Option<OnOff>,
202 vhost: Option<OnOff>,
203 vhostfd: Option<String>,
204 vhostforce: Option<OnOff>,
205 queues: Option<usize>,
206 poll_us: Option<usize>,
207}
208
209impl ToCommand for Tap {
210 fn to_command(&self) -> Vec<String> {
211 let mut args = vec!["tap".to_string(), format!("id={}", self.id.to_string())];
212
213 if let Some(fd) = &self.fd {
214 args.push(format!("fd={}", fd));
215 }
216 if let Some(fds) = &self.fds {
217 args.push(format!("fds={}", fds.join(":")));
218 }
219 if let Some(ifname) = &self.ifname {
220 args.push(format!("ifname={}", ifname));
221 }
222 if let Some(script) = &self.script {
223 args.push(format!("script={}", script.to_command().join("")));
224 }
225 if let Some(downscript) = &self.downscript {
226 args.push(format!("downscript={}", downscript.to_command().join("")));
227 }
228 if let Some(br) = &self.br {
229 args.push(format!("br={}", br));
230 }
231 if let Some(helper) = &self.helper {
232 args.push(format!("helper={}", helper));
233 }
234 if let Some(sndbuf) = self.sndbuf {
235 args.push(format!("sndbuf={}", sndbuf));
236 }
237 if let Some(vnet_hdr) = &self.vnet_hdr {
238 args.push(format!("vnet_hdr={}", vnet_hdr.to_arg()));
239 }
240 if let Some(vhost) = &self.vhost {
241 args.push(format!("vhost={}", vhost.to_arg()));
242 }
243 if let Some(vhostfd) = &self.vhostfd {
244 args.push(format!("vhostfd={}", vhostfd));
245 }
246 if let Some(vhostforce) = &self.vhostforce {
247 args.push(format!("vhostforce={}", vhostforce.to_arg()));
248 }
249 if let Some(queues) = self.queues {
250 args.push(format!("queues={}", queues));
251 }
252 if let Some(poll_us) = self.poll_us {
253 args.push(format!("poll_us={}", poll_us));
254 }
255
256 args
257 }
258}
259#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
260pub struct Bridge {
261 id: String,
262 bridge: Option<String>,
263 helper: Option<String>,
264}
265
266impl ToCommand for Bridge {
267 fn to_command(&self) -> Vec<String> {
268 let mut cmd = vec!["bridge".to_string(), format!("id={}", self.id)];
269
270 if let Some(br) = &self.bridge {
271 cmd.push(format!("bridge={}", br));
272 }
273 if let Some(helper) = &self.helper {
274 cmd.push(format!("helper={}", helper));
275 }
276 cmd
277 }
278}
279
280#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
281pub struct HostAndPort {
282 host: String,
283 port: u16,
284}
285#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
286pub struct HostAndMaybePort {
287 host: String,
288 port: Option<u16>,
289}
290#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
291pub struct SocketRegular {
292 id: String,
293 fd: Option<String>,
294 listen: Option<HostAndMaybePort>,
295 connection: Option<HostAndPort>,
296}
297
298impl ToCommand for SocketRegular {
299 fn to_command(&self) -> Vec<String> {
300 let mut cmd = vec!["socket".to_string(), format!("id={}", self.id)];
301
302 if let Some(fd) = &self.fd {
303 cmd.push(format!("fd={}", fd));
304 }
305 if let Some(listen) = &self.listen {
306 if let Some(port) = &listen.port {
307 cmd.push(format!("listen={}:{}", listen.host, port));
308 } else {
309 cmd.push(format!("listen={}", listen.host));
310 }
311 if let Some(connection) = &self.connection {
312 cmd.push(format!("{}:{}", connection.host, connection.port));
313 }
314 }
315
316 vec![cmd.join(",")]
317 }
318}
319#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
320pub struct SocketMulticast {
321 id: String,
322 fd: Option<String>,
323 mcast: Option<HostAndPort>,
324 localaddr: Option<String>,
325}
326
327impl ToCommand for SocketMulticast {
328 fn to_command(&self) -> Vec<String> {
329 let mut cmd = vec!["socket".to_string(), format!("id={}", self.id)];
330
331 if let Some(fd) = &self.fd {
332 cmd.push(format!("fd={}", fd));
333 }
334 if let Some(mcast) = &self.mcast {
335 cmd.push(format!("mcast={}:{}", mcast.host, mcast.port));
336 }
337 if let Some(localaddr) = &self.localaddr {
338 cmd.push(format!("localaddr={}", localaddr));
339 }
340 vec![cmd.join(",")]
341 }
342}
343#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
344pub struct SocketUdpTunnel {
345 id: String,
346 fd: Option<String>,
347 udp: Option<HostAndPort>,
348 localaddr: Option<HostAndPort>,
349}
350
351impl ToCommand for SocketUdpTunnel {
352 fn to_command(&self) -> Vec<String> {
353 let mut cmd = vec!["socket".to_string(), format!("id={}", self.id)];
354
355 if let Some(fd) = &self.fd {
356 cmd.push(format!("fd={}", fd));
357 }
358 if let Some(udp) = &self.udp {
359 cmd.push(format!("udp={}:{}", udp.host, udp.port));
360 }
361 if let Some(localaddr) = &self.localaddr {
362 cmd.push(format!("localaddr={}:{}", localaddr.host, localaddr.port));
363 }
364 vec![cmd.join(",")]
365 }
366}
367
368#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
369pub enum Socket {
370 SocketRegular(SocketRegular),
371 Multicast(SocketMulticast),
372 UDPTunnel(SocketUdpTunnel),
373}
374
375impl ToCommand for Socket {
376 fn to_command(&self) -> Vec<String> {
377 match self {
378 Socket::SocketRegular(s) => s.to_command(),
379 Socket::Multicast(s) => s.to_command(),
380 Socket::UDPTunnel(s) => s.to_command(),
381 }
382 }
383}
384#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
385pub struct StreamOverTcp {
386 id: String,
387 server: Option<OnOff>,
388 addr_host: String,
389 addr_port: u16,
390 to: Option<u16>,
391 numeric: Option<OnOff>,
392 keep_alive: Option<OnOff>,
393 mptcp: Option<OnOff>,
394 addr_ipv4: Option<OnOff>,
395 addr_ipv6: Option<OnOff>,
396 reconnect_ms: Option<usize>,
397}
398
399impl ToCommand for StreamOverTcp {
400 fn to_command(&self) -> Vec<String> {
401 let mut cmd = vec!["stream".to_string(), format!("id={}", self.id)];
402
403 if let Some(server) = &self.server {
404 cmd.push(format!("server={}", server.to_arg()));
405 }
406 cmd.push("add.type=inet".to_string());
407 cmd.push(format!("addr.host={}", self.addr_host));
408 cmd.push(format!("addr.port={}", self.addr_port));
409 if let Some(to) = &self.to {
410 cmd.push(format!("to={}", to));
411 }
412 if let Some(numeric) = &self.numeric {
413 cmd.push(format!("numeric={}", numeric.to_arg()));
414 }
415 if let Some(keep_alive) = &self.keep_alive {
416 cmd.push(format!("keep-alive={}", keep_alive.to_arg()));
417 }
418 if let Some(mptcp) = &self.mptcp {
419 cmd.push(format!("mptcp={}", mptcp.to_arg()));
420 }
421 if let Some(ipv4) = &self.addr_ipv4 {
422 cmd.push(format!("addr.ipv4={}", ipv4.to_arg()));
423 }
424 if let Some(ipv6) = &self.addr_ipv6 {
425 cmd.push(format!("addr.ipv6={}", ipv6.to_arg()));
426 }
427 if let Some(reconnect_ms) = self.reconnect_ms {
428 cmd.push(format!("reconnect-ms={}", reconnect_ms));
429 }
430 vec![cmd.join(",")]
431 }
432}
433#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
434pub struct StreamOverUds {
435 id: String,
436 server: Option<OnOff>,
437 addr_path: String,
438 abstract_arg: Option<OnOff>,
439 tight: Option<OnOff>,
440 reconnect_ms: Option<usize>,
441}
442
443impl ToCommand for StreamOverUds {
444 fn to_command(&self) -> Vec<String> {
445 let mut cmd = vec!["stream".to_string(), format!("id={}", self.id)];
446
447 if let Some(server) = &self.server {
448 cmd.push(format!("server={}", server.to_arg()));
449 }
450 cmd.push("add.type=unix".to_string());
451 cmd.push(format!("addr.path={}", self.addr_path));
452 if let Some(abstract_arg) = &self.abstract_arg {
453 cmd.push(format!("abstract={}", abstract_arg.to_arg()));
454 }
455 if let Some(tight) = &self.tight {
456 cmd.push(format!("tight={}", tight.to_arg()));
457 }
458 if let Some(reconnect_ms) = self.reconnect_ms {
459 cmd.push(format!("reconnect-ms={}", reconnect_ms));
460 }
461 vec![cmd.join(",")]
462 }
463}
464#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
465pub struct StreamOverFd {
466 id: String,
467 server: Option<OnOff>,
468 addr_str: String,
469 reconnect_ms: Option<usize>,
470}
471
472impl ToCommand for StreamOverFd {
473 fn to_command(&self) -> Vec<String> {
474 let mut cmd = vec!["stream".to_string(), format!("id={}", self.id)];
475
476 if let Some(server) = &self.server {
477 cmd.push(format!("server={}", server.to_arg()));
478 }
479 cmd.push("add.type=fd".to_string());
480 cmd.push(format!("addr.str={}", self.addr_str));
481 if let Some(reconnect_ms) = self.reconnect_ms {
482 cmd.push(format!("reconnect-ms={}", reconnect_ms));
483 }
484 vec![cmd.join(",")]
485 }
486}
487#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
488pub enum Stream {
489 StreamOverTcp(StreamOverTcp),
490 StreamOverUds(StreamOverUds),
491 StreamOverFd(StreamOverFd),
492}
493
494impl ToCommand for Stream {
495 fn to_command(&self) -> Vec<String> {
496 match self {
497 Stream::StreamOverTcp(s) => s.to_command(),
498 Stream::StreamOverUds(s) => s.to_command(),
499 Stream::StreamOverFd(s) => s.to_command(),
500 }
501 }
502}
503#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
504pub struct DgramMulticast {
505 id: String,
506 remote_host: String,
507 remote_port: u16,
508 local_host: Option<String>,
509}
510
511impl ToCommand for DgramMulticast {
512 fn to_command(&self) -> Vec<String> {
513 let mut args = vec![
514 "dgram".to_string(),
515 format!("id={}", self.id.to_string()),
516 "remote.type=inet".to_string(),
517 format!("remote.host={}", self.remote_host),
518 format!("remote.port={}", self.remote_port),
519 ];
520
521 if let Some(local_host) = &self.local_host {
522 args.push("local.type=inet".to_string());
523 args.push(format!("local.host={}", local_host));
524 }
525 args
526 }
527}
528#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
529pub struct DgramMulticastUdpFd {
530 id: String,
531 remote_host: String,
532 remote_port: u16,
533 local_str: Option<String>,
534}
535
536impl ToCommand for DgramMulticastUdpFd {
537 fn to_command(&self) -> Vec<String> {
538 let mut args = vec![
539 "dgram".to_string(),
540 format!("id={}", self.id.to_string()),
541 "remote.type=inet".to_string(),
542 format!("remote.host={}", self.remote_host),
543 format!("remote.port={}", self.remote_port),
544 ];
545
546 if let Some(local_str) = &self.local_str {
547 args.push("local.type=fd".to_string());
548 args.push(format!("local.str={}", local_str));
549 }
550 args
551 }
552}
553#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
554pub struct DgramSocket {
555 id: String,
556 local_host: String,
557 local_port: usize,
558 remote_host: Option<String>,
559 remote_port: Option<u16>,
560}
561
562impl ToCommand for DgramSocket {
563 fn to_command(&self) -> Vec<String> {
564 let mut args = vec![
565 "dgram".to_string(),
566 format!("id={}", self.id.to_string()),
567 "local.type=inet".to_string(),
568 format!("local.host={}", self.local_host),
569 format!("local.port={}", self.local_port),
570 ];
571
572 if let Some(remote_host) = &self.remote_host {
573 args.push("remote.type=inet".to_string());
574 args.push(format!("remote.host={}", remote_host));
575 }
576 if let Some(remote_port) = &self.remote_port {
577 args.push(format!("remote.port={}", remote_port));
578 }
579 args
580 }
581}
582
583#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
584pub struct DgramUds {
585 id: String,
586 local_path: PathBuf,
587 remote_path: Option<PathBuf>,
588}
589
590impl ToCommand for DgramUds {
591 fn to_command(&self) -> Vec<String> {
592 let mut args = vec![
593 "dgram".to_string(),
594 format!("id={}", self.id.to_string()),
595 "local.type=unix".to_string(),
596 format!("local.path={}", self.local_path.display()),
597 ];
598 if let Some(remote) = &self.remote_path {
599 args.push("remote.type=unix".to_string());
600 args.push(format!("remote.path={}", remote.display()));
601 }
602 args
603 }
604}
605#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
606pub struct DgramFd {
607 id: String,
608 local_str: String,
609}
610
611impl ToCommand for DgramFd {
612 fn to_command(&self) -> Vec<String> {
613 vec![
614 "dgram".to_string(),
615 format!("id={}", self.id.to_string()),
616 "local.type=fd".to_string(),
617 format!("local.str={}", self.local_str),
618 ]
619 }
620}
621#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
622pub enum Dgram {
623 DgramMulticast(DgramMulticast),
624 DgramMulticastUdpFd(DgramMulticastUdpFd),
625 DgramSocket(DgramSocket),
626 DgramUds(DgramUds),
627 DgramFd(DgramFd),
628}
629
630impl ToCommand for Dgram {
631 fn to_command(&self) -> Vec<String> {
632 match self {
633 Dgram::DgramMulticast(args) => args.to_command(),
634 Dgram::DgramMulticastUdpFd(args) => args.to_command(),
635 Dgram::DgramSocket(args) => args.to_command(),
636 Dgram::DgramUds(args) => args.to_command(),
637 Dgram::DgramFd(args) => args.to_command(),
638 }
639 }
640}
641#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
642pub struct Vde {
643 id: String,
644 sock: Option<PathBuf>,
645 port: Option<u16>,
646 group: Option<String>,
647 mode: Option<String>,
648}
649
650impl ToCommand for Vde {
651 fn to_command(&self) -> Vec<String> {
652 let mut args = vec!["vde".to_string(), format!("id={}", self.id.to_string())];
653
654 if let Some(sock) = &self.sock {
655 args.push(format!("sock={}", sock.display()));
656 }
657 if let Some(port) = self.port {
658 args.push(format!("port={}", port));
659 }
660 if let Some(group) = &self.group {
661 args.push(format!("group={}", group));
662 }
663 if let Some(mode) = &self.mode {
664 args.push(format!("mode={}", mode));
665 }
666 args
667 }
668}
669#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
670pub struct NetMap {
671 id: String,
672 ifname: String,
673 devname: Option<String>,
674}
675
676impl ToCommand for NetMap {
677 fn to_command(&self) -> Vec<String> {
678 let mut args = vec!["netmap".to_string(), format!("id={}", self.id.to_string())];
679 args.push(format!("ifname={}", self.ifname));
680 if let Some(devname) = &self.devname {
681 args.push(format!("devname={}", devname));
682 }
683 args
684 }
685}
686#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
687pub enum NativeSkb {
688 Native,
689 Skb,
690}
691
692impl ToArg for NativeSkb {
693 fn to_arg(&self) -> &str {
694 match self {
695 NativeSkb::Native => "native",
696 NativeSkb::Skb => "skb",
697 }
698 }
699}
700#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
701pub struct AfXdp {
702 id: String,
703 ifname: String,
704 mode: Option<NativeSkb>,
705 force_copy: Option<OnOff>,
706 queues: Option<usize>,
707 start_queue: Option<usize>,
708 inhibit: Option<OnOff>,
709 sock_fds: Option<Vec<String>>,
710}
711
712impl ToCommand for AfXdp {
713 fn to_command(&self) -> Vec<String> {
714 let mut args = vec![
715 "af-xdp".to_string(),
716 format!("id={}", self.id.to_string()),
717 format!("ifname={}", self.ifname),
718 ];
719
720 if let Some(mode) = &self.mode {
721 args.push(format!("mode={}", mode.to_arg()));
722 }
723 if let Some(force_copy) = &self.force_copy {
724 args.push(format!("force-copy={}", force_copy.to_arg()));
725 }
726 if let Some(queues) = self.queues {
727 args.push(format!("queues={}", queues));
728 }
729 if let Some(start_queue) = self.start_queue {
730 args.push(format!("start-queue={}", start_queue));
731 }
732 if let Some(inhibit) = &self.inhibit {
733 args.push(format!("inhibit={}", inhibit.to_arg()));
734 }
735 if let Some(sock_fds) = &self.sock_fds {
736 args.push(format!("sock-fds={}", sock_fds.join(":")));
737 }
738 args
739 }
740}
741#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
742pub struct VhostUser {
743 id: String,
744 chardev: String,
745 vhostforce: Option<OnOff>,
746}
747
748impl ToCommand for VhostUser {
749 fn to_command(&self) -> Vec<String> {
750 let mut args = vec![
751 "vhost-user".to_string(),
752 format!("id={}", self.id.to_string()),
753 format!("chardev={}", self.chardev),
754 ];
755
756 if let Some(vhostforce) = &self.vhostforce {
757 args.push(format!("vhostforce={}", vhostforce.to_arg()));
758 }
759 args
760 }
761}
762#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
763pub struct VhostVdpa {
764 id: String,
765 vhostdev: Option<PathBuf>,
766 vhostfd: Option<String>,
767}
768
769impl ToCommand for VhostVdpa {
770 fn to_command(&self) -> Vec<String> {
771 let mut args = vec![
772 "vhost-vdpa".to_string(),
773 format!("id={}", self.id.to_string()),
774 ];
775 if let Some(vhostdev) = &self.vhostdev {
776 args.push(format!("vhostdev={}", vhostdev.to_str().unwrap()));
777 }
778 if let Some(vhostfd) = &self.vhostfd {
779 args.push(format!("vhostfd={}", vhostfd));
780 }
781 args
782 }
783}
784#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
785pub struct VmnetHost {
786 id: String,
787 isolated: Option<OnOff>,
788 net_uuid: Option<String>,
789 start_address: Option<String>,
790 end_address: Option<String>,
791 subnet_mask: Option<String>,
792}
793
794impl ToCommand for VmnetHost {
795 fn to_command(&self) -> Vec<String> {
796 let mut args = vec![
797 "vmnet-host".to_string(),
798 format!("id={}", self.id.to_string()),
799 ];
800
801 if let Some(isolated) = &self.isolated {
802 args.push(format!("isolated={}", isolated.to_arg()));
803 }
804 if let Some(net_uuid) = &self.net_uuid {
805 args.push(format!("net_uuid={}", net_uuid));
806 }
807 if let Some(start_address) = &self.start_address {
808 args.push(format!("start-address={}", start_address));
809 }
810 if let Some(end_address) = &self.end_address {
811 args.push(format!("end-address={}", end_address));
812 }
813 if let Some(subnet_mask) = &self.subnet_mask {
814 args.push(format!("subnet-mask={}", subnet_mask));
815 }
816 args
817 }
818}
819
820#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
821pub struct VmnetShared {
822 id: String,
823 isolated: Option<OnOff>,
824 nat66_prefix: Option<String>,
825 start_address: Option<String>,
826 end_address: Option<String>,
827 subnet_mask: Option<String>,
828}
829
830impl ToCommand for VmnetShared {
831 fn to_command(&self) -> Vec<String> {
832 let mut args = vec![
833 "vmnet-shared".to_string(),
834 format!("id={}", self.id.to_string()),
835 ];
836
837 if let Some(isolated) = &self.isolated {
838 args.push(format!("isolated={}", isolated.to_arg()));
839 }
840 if let Some(nat66_prefix) = &self.nat66_prefix {
841 args.push(format!("nat66-prefix={}", nat66_prefix));
842 }
843 if let Some(start_address) = &self.start_address {
844 args.push(format!("start-address={}", start_address));
845 }
846 if let Some(end_address) = &self.end_address {
847 args.push(format!("end-address={}", end_address));
848 }
849 if let Some(subnet_mask) = &self.subnet_mask {
850 args.push(format!("subnet-mask={}", subnet_mask));
851 }
852 args
853 }
854}
855#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
856pub struct VmnetBridged {
857 id: String,
858 ifname: String,
859 isolated: Option<OnOff>,
860}
861
862impl ToCommand for VmnetBridged {
863 fn to_command(&self) -> Vec<String> {
864 let mut args = vec![
865 "vmnet-bridged".to_string(),
866 format!("id={}", self.id.to_string()),
867 format!("ifname={}", self.ifname),
868 ];
869
870 if let Some(isolated) = &self.isolated {
871 args.push(format!("isolated={}", isolated.to_arg()));
872 }
873 args
874 }
875}
876#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder)]
877pub struct Hubport {
878 id: String,
879 hubid: usize,
880 netdev: Option<String>,
881}
882
883impl ToCommand for Hubport {
884 fn to_command(&self) -> Vec<String> {
885 let mut args = vec![
886 "hubport".to_string(),
887 format!("id={}", self.id.to_string()),
888 format!("hubid={}", self.hubid),
889 ];
890
891 if let Some(netdev) = &self.netdev {
892 args.push(format!("netdev={}", netdev));
893 }
894 args
895 }
896}
897#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)]
898pub enum NetDev {
899 User(User),
900 Tap(Tap),
902 Bridge(Bridge),
903 Socket(Socket),
904 Stream(Stream),
905 Dgram(Dgram),
906 Vde(Vde),
907 Netmap(NetMap),
908 AfXdp(AfXdp),
909 VhostUser(VhostUser),
910 VhostVdpa(VhostVdpa),
911 VmnetHost(VmnetHost),
912 VmnetShared(VmnetShared),
913 VmnetBridged(VmnetBridged),
914 Hubport(Hubport),
915}
916
917impl ToCommand for NetDev {
918 fn to_command(&self) -> Vec<String> {
919 let mut cmd = vec![];
920
921 cmd.push("-netdev".to_string());
922
923 let mut args: Vec<String> = vec![];
924
925 match self {
926 NetDev::User(user) => {
927 args.append(&mut user.to_command());
928 }
929 NetDev::Tap(tap) => {
931 args.append(&mut tap.to_command());
932 }
933 NetDev::Bridge(bridge) => {
934 args.append(&mut bridge.to_command());
935 }
936 NetDev::Socket(socket) => {
937 args.append(&mut socket.to_command());
938 }
939 NetDev::Stream(stream) => {
940 args.append(&mut stream.to_command());
941 }
942 NetDev::Dgram(dgram) => {
943 args.append(&mut dgram.to_command());
944 }
945 NetDev::Vde(vde) => {
946 args.append(&mut vde.to_command());
947 }
948 NetDev::Netmap(netmap) => {
949 args.append(&mut netmap.to_command());
950 }
951 NetDev::AfXdp(af_xdp) => {
952 args.append(&mut af_xdp.to_command());
953 }
954 NetDev::VhostUser(vhost_user) => {
955 args.append(&mut vhost_user.to_command());
956 }
957 NetDev::VhostVdpa(vhost_vdpa) => {
958 args.append(&mut vhost_vdpa.to_command());
959 }
960 NetDev::VmnetHost(vmnet_host) => {
961 args.append(&mut vmnet_host.to_command());
962 }
963 NetDev::VmnetShared(vmnet_shared) => {
964 args.append(&mut vmnet_shared.to_command());
965 }
966 NetDev::VmnetBridged(vmnet_bridged) => {
967 args.append(&mut vmnet_bridged.to_command());
968 }
969 NetDev::Hubport(hubport) => {
970 args.append(&mut hubport.to_command());
971 }
972 }
973 cmd.push(args.join(","));
974 cmd
975 }
976}