1use serde::{Deserialize, Serialize};
4
5use crate::{BaseInterface, InterfaceType};
6
7#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8#[non_exhaustive]
9pub struct VxlanInterface {
27 #[serde(flatten)]
28 pub base: BaseInterface,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub vxlan: Option<VxlanConfig>,
31}
32
33impl Default for VxlanInterface {
34 fn default() -> Self {
35 Self {
36 base: BaseInterface {
37 iface_type: InterfaceType::Vxlan,
38 ..Default::default()
39 },
40 vxlan: None,
41 }
42 }
43}
44
45impl VxlanInterface {
46 pub fn new() -> Self {
47 Self::default()
48 }
49
50 pub(crate) fn parent(&self) -> Option<&str> {
51 self.vxlan.as_ref().and_then(|cfg| {
52 if cfg.base_iface.is_empty() {
53 None
54 } else {
55 Some(cfg.base_iface.as_str())
56 }
57 })
58 }
59
60 pub(crate) fn change_parent_name(&mut self, name: &str) {
61 if let Some(vxlan_conf) = self.vxlan.as_mut() {
62 vxlan_conf.base_iface = name.to_string();
63 }
64 }
65}
66
67#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
68#[serde(rename_all = "kebab-case", deny_unknown_fields)]
69#[non_exhaustive]
70pub struct VxlanConfig {
71 #[serde(default, skip_serializing_if = "String::is_empty")]
72 pub base_iface: String,
73 #[serde(deserialize_with = "crate::deserializer::u32_or_string")]
74 pub id: u32,
75 #[serde(skip_serializing_if = "Option::is_none")]
76 pub learning: Option<bool>,
77 #[serde(skip_serializing_if = "Option::is_none")]
78 pub local: Option<std::net::IpAddr>,
79 #[serde(skip_serializing_if = "Option::is_none")]
80 pub remote: Option<std::net::IpAddr>,
81 #[serde(
82 rename = "destination-port",
83 default,
84 deserialize_with = "crate::deserializer::option_u16_or_string",
85 skip_serializing_if = "Option::is_none"
86 )]
87 pub dst_port: Option<u16>,
89}