1use crate::communication::{
2 AbstractPdu, AbstractPhysicalChannel, CommunicationDirection, EthernetCluster, EthernetCommunicationConnector,
3 GeneralPurposePdu, Pdu, PduCollectionTrigger, PduTriggering,
4};
5use crate::{
6 AbstractionElement, ArPackage, AutosarAbstractionError, EcuInstance, IdentifiableAbstractionElement,
7 abstraction_element,
8};
9use autosar_data::{AutosarVersion, Element, ElementName, EnumItem};
10
11mod networkendpoint;
12mod soad_old;
13mod socketaddress;
14mod someip;
15mod someip_old;
16
17pub use networkendpoint::*;
18pub use soad_old::*;
19pub use socketaddress::*;
20pub use someip::*;
21pub use someip_old::*;
22
23use super::PhysicalChannel;
24
25#[derive(Debug, Clone, PartialEq)]
29pub struct EthernetVlanInfo {
30 pub vlan_name: String,
32 pub vlan_id: u16,
34}
35
36#[derive(Debug, Clone, PartialEq, Eq, Hash)]
40pub struct EthernetPhysicalChannel(Element);
41abstraction_element!(EthernetPhysicalChannel, EthernetPhysicalChannel);
42impl IdentifiableAbstractionElement for EthernetPhysicalChannel {}
43
44impl EthernetPhysicalChannel {
45 pub(crate) fn new(
47 name: &str,
48 parent: &Element,
49 vlan_info: Option<&EthernetVlanInfo>,
50 ) -> Result<EthernetPhysicalChannel, AutosarAbstractionError> {
51 let physical_channel_elem = parent.create_named_sub_element(ElementName::EthernetPhysicalChannel, name)?;
52 let physical_channel = Self(physical_channel_elem);
53
54 let result = physical_channel.set_vlan_info(vlan_info);
56 if let Err(error) = result {
57 let _ = parent.remove_sub_element(physical_channel.element().clone());
59 return Err(error);
60 }
61
62 let _ = physical_channel
64 .0
65 .create_sub_element(ElementName::Category)
66 .and_then(|cat| cat.set_character_data("WIRED"));
67
68 Ok(physical_channel)
69 }
70
71 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
73 for scb in self.socket_connection_bundles() {
75 scb.remove(deep)?;
76 }
77
78 for sa in self.socket_addresses() {
80 sa.remove(deep)?;
81 }
82
83 for ne in self.network_endpoints() {
85 ne.remove(deep)?;
86 }
87
88 for pt in self.pdu_triggerings() {
90 pt.remove(deep)?;
91 }
92
93 for st in self.signal_triggerings() {
95 st.remove(deep)?;
96 }
97
98 for connector in self.connectors() {
100 connector.remove(deep)?;
101 }
102
103 AbstractionElement::remove(self, deep)
104 }
105
106 pub fn set_vlan_info(&self, vlan_info: Option<&EthernetVlanInfo>) -> Result<(), AutosarAbstractionError> {
137 let cluster = self.cluster()?;
138 for channel in cluster.physical_channels() {
141 if &channel != self {
142 let other_vlan_info = channel.vlan_info();
143 if let (Some(v1), Some(v2)) = (&vlan_info, &other_vlan_info) {
144 if v1.vlan_id == v2.vlan_id {
145 return Err(AutosarAbstractionError::ItemAlreadyExists);
147 }
148 } else if other_vlan_info.is_none() && vlan_info.is_none() {
149 return Err(AutosarAbstractionError::ItemAlreadyExists);
151 }
152 }
153 }
154
155 let _ = self.element().remove_sub_element_kind(ElementName::Vlan);
157 if let Some(vlan_info) = vlan_info {
159 let _ = self
160 .element()
161 .create_named_sub_element(ElementName::Vlan, &vlan_info.vlan_name)
162 .and_then(|vlan| vlan.create_sub_element(ElementName::VlanIdentifier))
163 .and_then(|vlan_id| vlan_id.set_character_data(vlan_info.vlan_id.to_string()));
164 }
165
166 Ok(())
167 }
168
169 #[must_use]
194 pub fn vlan_info(&self) -> Option<EthernetVlanInfo> {
195 let vlan = self.0.get_sub_element(ElementName::Vlan)?;
196 let vlan_id = vlan
197 .get_sub_element(ElementName::VlanIdentifier)?
198 .character_data()?
199 .parse_integer::<u16>()?;
200 Some(EthernetVlanInfo {
201 vlan_name: vlan.item_name()?,
202 vlan_id,
203 })
204 }
205
206 pub fn cluster(&self) -> Result<EthernetCluster, AutosarAbstractionError> {
228 let cluster_elem = self.0.named_parent()?.unwrap();
229 EthernetCluster::try_from(cluster_elem)
230 }
231
232 pub fn create_network_endpoint(
264 &self,
265 name: &str,
266 address: NetworkEndpointAddress,
267 ecu: Option<&EcuInstance>,
268 ) -> Result<NetworkEndpoint, AutosarAbstractionError> {
269 let network_endpoint = NetworkEndpoint::new(name, self, address)?;
270
271 if let Some(ecu_instance) = ecu {
272 let version = self.0.min_version()?;
273 if version <= AutosarVersion::Autosar_00046 {
274 let ne_element = network_endpoint.element();
275
276 if let Some(connector) = self.ecu_connector(ecu_instance).map(|conn| conn.element().clone()) {
278 let _ = connector
279 .get_or_create_sub_element(ElementName::NetworkEndpointRefs)
280 .and_then(|ner| ner.create_sub_element(ElementName::NetworkEndpointRef))
281 .and_then(|ner| ner.set_reference_target(ne_element));
282 } else {
283 let _ = self
286 .element()
287 .get_sub_element(ElementName::NetworkEndpoints)
288 .and_then(|nes| nes.remove_sub_element(ne_element.clone()).ok());
289 return Err(AutosarAbstractionError::InvalidParameter(
290 "The ECU must be connected to the channel".to_string(),
291 ));
292 }
293 }
294 }
295
296 Ok(network_endpoint)
297 }
298
299 pub fn network_endpoints(&self) -> impl Iterator<Item = NetworkEndpoint> + Send + use<> {
327 self.element()
328 .get_sub_element(ElementName::NetworkEndpoints)
329 .into_iter()
330 .flat_map(|ne| ne.sub_elements())
331 .filter_map(|ne_elem| NetworkEndpoint::try_from(ne_elem).ok())
332 }
333
334 pub fn create_socket_address(
375 &self,
376 name: &str,
377 network_endpoint: &NetworkEndpoint,
378 tp_config: &TpConfig,
379 sa_type: SocketAddressType,
380 ) -> Result<SocketAddress, AutosarAbstractionError> {
381 SocketAddress::new(name, self, network_endpoint, tp_config, sa_type)
382 }
383
384 pub fn socket_addresses(&self) -> impl Iterator<Item = SocketAddress> + Send + use<> {
418 self.element()
419 .get_sub_element(ElementName::SoAdConfig)
420 .and_then(|sc| sc.get_sub_element(ElementName::SocketAddresss))
421 .into_iter()
422 .flat_map(|sa| sa.sub_elements())
423 .filter_map(|sa_elem| SocketAddress::try_from(sa_elem).ok())
424 }
425
426 pub fn create_socket_connection_bundle(
457 &self,
458 name: &str,
459 server_port: &SocketAddress,
460 ) -> Result<SocketConnectionBundle, AutosarAbstractionError> {
461 let soadcfg = self.0.get_or_create_sub_element(ElementName::SoAdConfig)?;
462 let connections = soadcfg.get_or_create_sub_element(ElementName::ConnectionBundles)?;
463
464 SocketConnectionBundle::new(name, server_port, &connections)
465 }
466
467 pub fn socket_connection_bundles(&self) -> impl Iterator<Item = SocketConnectionBundle> + Send + use<> {
472 self.element()
473 .get_sub_element(ElementName::SoAdConfig)
474 .and_then(|sc| sc.get_sub_element(ElementName::ConnectionBundles))
475 .into_iter()
476 .flat_map(|cb| cb.sub_elements())
477 .filter_map(|cb_elem| SocketConnectionBundle::try_from(cb_elem).ok())
478 }
479
480 pub fn create_static_socket_connection_pair(
523 &self,
524 name: &str,
525 port_1: &SocketAddress,
526 port_2: &SocketAddress,
527 tcp_connect_timeout: Option<f64>,
528 ) -> Result<(StaticSocketConnection, StaticSocketConnection), AutosarAbstractionError> {
529 let ssc1 = port_1.create_static_socket_connection(name, port_2, Some(TcpRole::Connect), tcp_connect_timeout)?;
530 let ssc2 = port_2.create_static_socket_connection(name, port_1, Some(TcpRole::Listen), tcp_connect_timeout)?;
531 Ok((ssc1, ssc2))
532 }
533
534 pub fn configure_service_discovery_for_ecu(
617 &self,
618 ecu: &EcuInstance,
619 unicast_socket: &SocketAddress,
620 unicast_rx_pdu: &GeneralPurposePdu,
621 unicast_tx_pdu: &GeneralPurposePdu,
622 common_config: &CommonServiceDiscoveryConfig,
623 ) -> Result<(), AutosarAbstractionError> {
624 let version = self.0.min_version()?;
625
626 if self.ecu_connector(ecu).is_none() {
628 return Err(AutosarAbstractionError::InvalidParameter(
629 "The ECU must be connected to the channel".to_string(),
630 ));
631 };
632
633 let use_scb = version < AutosarVersion::Autosar_00048
636 || self.has_socket_connections()
637 || !common_config.prefer_static_socket_connections;
638
639 if unicast_socket.physical_channel()? != *self
641 || common_config.multicast_rx_socket.physical_channel()? != *self
642 || common_config.remote_socket.physical_channel()? != *self
643 {
644 return Err(AutosarAbstractionError::InvalidParameter(
645 "All sockets must be part of the channel".to_string(),
646 ));
647 }
648
649 match unicast_socket.socket_address_type() {
651 Some(SocketAddressType::Unicast(opt_socket_ecu)) => {
652 if let Some(socket_ecu) = opt_socket_ecu
653 && &socket_ecu != ecu
654 {
655 return Err(AutosarAbstractionError::InvalidParameter(
656 "The unicast socket belongs to a different ECU".to_string(),
657 ));
658 }
659 }
660 None => {
661 unicast_socket.set_unicast_ecu(ecu)?;
663 }
664 _ => {
665 return Err(AutosarAbstractionError::InvalidParameter(
666 "The unicast socket is not configured as Unicast".to_string(),
667 ));
668 }
669 }
670
671 match common_config.multicast_rx_socket.socket_address_type() {
674 Some(SocketAddressType::Multicast(_)) | None => {
675 common_config.multicast_rx_socket.add_multicast_ecu(ecu)?;
676 }
677 _ => {
678 return Err(AutosarAbstractionError::InvalidParameter(
679 "The multicast rx socket is not configured as Multicast".to_string(),
680 ));
681 }
682 }
683
684 let Some(TpConfig::UdpTp {
686 port_number: unicast_port,
687 ..
688 }) = unicast_socket.tp_config()
689 else {
690 return Err(AutosarAbstractionError::InvalidParameter(
691 "The unicast port must use UDP".to_string(),
692 ));
693 };
694 let Some(TpConfig::UdpTp {
695 port_number: multicast_rx_port,
696 ..
697 }) = common_config.multicast_rx_socket.tp_config()
698 else {
699 return Err(AutosarAbstractionError::InvalidParameter(
700 "The multicast rx port must use UDP".to_string(),
701 ));
702 };
703 let Some(TpConfig::UdpTp {
704 port_number: remote_port,
705 port_dynamically_assigned: remote_dynamically_assigned,
706 }) = common_config.remote_socket.tp_config()
707 else {
708 return Err(AutosarAbstractionError::InvalidParameter(
709 "The remote port must use UDP".to_string(),
710 ));
711 };
712 if unicast_port.is_none() || unicast_port != multicast_rx_port {
713 return Err(AutosarAbstractionError::InvalidParameter(
714 "All local UDP ports must use the same port number".to_string(),
715 ));
716 }
717 if remote_port != Some(0) && remote_dynamically_assigned != Some(true) {
720 return Err(AutosarAbstractionError::InvalidParameter(
721 "The remote UDP port must be 0 / dynamically assigned".to_string(),
722 ));
723 }
724
725 let Some(remote_network_endpoint) = common_config.remote_socket.network_endpoint() else {
727 return Err(AutosarAbstractionError::InvalidParameter(
728 "The remote socket must have a network endpoint".to_string(),
729 ));
730 };
731 if !remote_network_endpoint.addresses().all(|neaddr| match neaddr {
732 NetworkEndpointAddress::IPv4 { address, .. } => address == Some("ANY".to_string()),
733 NetworkEndpointAddress::IPv6 { address, .. } => address == Some("ANY".to_string()),
734 }) {
735 return Err(AutosarAbstractionError::InvalidParameter(
736 "The IP (v4/v6) address of the remote socket must be set to ANY".to_string(),
737 ));
738 }
739
740 if use_scb {
742 self.configure_sd_socket_connection_bundle(
743 ecu,
744 unicast_socket,
745 unicast_tx_pdu,
746 unicast_rx_pdu,
747 common_config,
748 )?;
749 } else {
750 self.configure_sd_static_socket_connection(
751 common_config,
752 unicast_socket,
753 unicast_rx_pdu,
754 ecu,
755 unicast_tx_pdu,
756 )?;
757 }
758
759 Ok(())
760 }
761
762 fn configure_sd_socket_connection_bundle(
764 &self,
765 ecu: &EcuInstance,
766 unicast_socket: &SocketAddress,
767 unicast_tx_pdu: &GeneralPurposePdu,
768 unicast_rx_pdu: &GeneralPurposePdu,
769 common_config: &CommonServiceDiscoveryConfig<'_>,
770 ) -> Result<(), AutosarAbstractionError> {
771 let name_prefix = common_config.name_prefix.unwrap_or("");
772 let ecu_name = ecu.name().unwrap_or("unnamed".to_string());
773
774 let connection_bundles = self
775 .element()
776 .get_or_create_sub_element(ElementName::SoAdConfig)?
777 .get_or_create_sub_element(ElementName::ConnectionBundles)?;
778
779 let scb_unicast = self.socket_connection_bundles().find(|scb| {
781 scb.server_port().is_some_and(|sp| &sp == unicast_socket)
782 && scb.bundled_connections().any(|sc| {
783 sc.client_ip_addr_from_connection_request() == Some(true)
784 && sc.client_port().is_some_and(|cp| &cp == common_config.remote_socket)
785 && sc.pdu_triggerings().count() == 2
786 })
787 });
788
789 if scb_unicast.is_none() {
790 let scb_name = format!("{name_prefix}SD_Unicast_{ecu_name}");
792 let scb = SocketConnectionBundle::new(&scb_name, unicast_socket, &connection_bundles)?;
793 let conn = scb.create_bundled_connection(common_config.remote_socket)?;
794 conn.set_client_ip_addr_from_connection_request(Some(true))?;
795 conn.set_client_port_from_connection_request(Some(true))?;
796 let (_, pt_tx) = conn.create_socket_connection_ipdu_identifier(
797 unicast_tx_pdu,
798 SocketConnection::SD_HEADER_ID,
799 None,
800 Some(PduCollectionTrigger::Always),
801 )?;
802 let (_, pt_rx) = conn.create_socket_connection_ipdu_identifier(
803 unicast_rx_pdu,
804 SocketConnection::SD_HEADER_ID,
805 None,
806 Some(PduCollectionTrigger::Always),
807 )?;
808 pt_tx.create_pdu_port(ecu, CommunicationDirection::Out)?;
809 pt_rx.create_pdu_port(ecu, CommunicationDirection::In)?;
810 }
811
812 let scb_multicast_opt = self.socket_connection_bundles().find(|scb| {
814 scb.server_port()
815 .is_some_and(|sp| &sp == common_config.multicast_rx_socket)
816 && scb.bundled_connections().any(|sc| {
817 sc.client_ip_addr_from_connection_request() == Some(true)
818 && sc.client_port().is_some_and(|cp| &cp == common_config.remote_socket)
819 && sc.pdu_triggerings().count() == 1
820 })
821 });
822
823 let scb_multicast_pt = if let Some(pt) = scb_multicast_opt
824 .and_then(|scb| scb.bundled_connections().next())
825 .and_then(|sc| sc.pdu_triggerings().next())
826 {
827 pt
829 } else {
830 let scb_name = format!("{name_prefix}SD_Multicast_Rx");
832 let scb = SocketConnectionBundle::new(&scb_name, common_config.multicast_rx_socket, &connection_bundles)?;
833 let conn = scb.create_bundled_connection(common_config.remote_socket)?;
834 conn.set_client_ip_addr_from_connection_request(Some(true))?;
835 conn.set_client_port_from_connection_request(Some(true))?;
836 let (_, pt) = conn.create_socket_connection_ipdu_identifier(
838 common_config.multicast_rx_pdu,
839 SocketConnection::SD_HEADER_ID,
840 None,
841 Some(PduCollectionTrigger::Always),
842 )?;
843 pt
844 };
845 scb_multicast_pt.create_pdu_port(ecu, CommunicationDirection::In)?;
847
848 Ok(())
849 }
850
851 fn configure_sd_static_socket_connection(
853 &self,
854 common_config: &CommonServiceDiscoveryConfig<'_>,
855 unicast_socket: &SocketAddress,
856 unicast_rx_pdu: &GeneralPurposePdu,
857 ecu: &EcuInstance,
858 unicast_tx_pdu: &GeneralPurposePdu,
859 ) -> Result<(), AutosarAbstractionError> {
860 let name_prefix = common_config.name_prefix.unwrap_or("");
861 let ecu_name = ecu.name().unwrap_or("unnamed".to_string());
862
863 let Some(ipdu_identifier_set) = common_config.ipdu_identifier_set else {
864 return Err(AutosarAbstractionError::InvalidParameter(
865 "An IPduIdentifierSet is required for StaticSocketConnections".to_string(),
866 ));
867 };
868 let ssc_unicast = unicast_socket.static_socket_connections().find(|ssc| {
869 ssc.remote_socket().is_some_and(|rs| &rs == common_config.remote_socket)
870 && ssc.ipdu_identifiers().count() == 2
871 });
872
873 if ssc_unicast.is_none() {
874 let name = format!("{name_prefix}SD_Unicast_{ecu_name}");
876 let ssc = unicast_socket.create_static_socket_connection(&name, common_config.remote_socket, None, None)?;
877 let name = format!("{name_prefix}SD_Unicast_Rx_{ecu_name}");
879 let idpu_identifier_rx = ipdu_identifier_set.create_socon_ipdu_identifier(
880 &name,
881 unicast_rx_pdu,
882 self,
883 Some(SoConIPduIdentifier::SD_HEADER_ID),
884 None,
885 Some(PduCollectionTrigger::Always),
886 )?;
887 idpu_identifier_rx
889 .pdu_triggering()
890 .unwrap()
891 .create_pdu_port(ecu, CommunicationDirection::In)?;
892 let name = format!("{name_prefix}SD_Unicast_Tx_{ecu_name}");
894 let idpu_identifier_tx = ipdu_identifier_set.create_socon_ipdu_identifier(
895 &name,
896 unicast_tx_pdu,
897 self,
898 Some(SoConIPduIdentifier::SD_HEADER_ID),
899 None,
900 Some(PduCollectionTrigger::Always),
901 )?;
902 idpu_identifier_tx
904 .pdu_triggering()
905 .unwrap()
906 .create_pdu_port(ecu, CommunicationDirection::Out)?;
907 ssc.add_ipdu_identifier(&idpu_identifier_rx)?;
908 ssc.add_ipdu_identifier(&idpu_identifier_tx)?;
909 }
910
911 let ssc_multicast = common_config
913 .multicast_rx_socket
914 .static_socket_connections()
915 .find(|ssc| {
916 ssc.remote_socket().is_some_and(|rs| &rs == common_config.remote_socket)
917 && ssc.ipdu_identifiers().count() == 1
918 });
919
920 let pt_multicast_rx = if let Some(pt) = ssc_multicast
921 .and_then(|ssc| ssc.ipdu_identifiers().next())
922 .and_then(|ipi| ipi.pdu_triggering())
923 {
924 pt
926 } else {
927 let name = format!("{name_prefix}SD_Multicast_Rx");
929 let ssc = common_config.multicast_rx_socket.create_static_socket_connection(
930 &name,
931 common_config.remote_socket,
932 None,
933 None,
934 )?;
935 let idpu_identifier_mc_rx = ipdu_identifier_set.create_socon_ipdu_identifier(
936 &name,
937 common_config.multicast_rx_pdu,
938 self,
939 Some(SoConIPduIdentifier::SD_HEADER_ID),
940 None,
941 Some(PduCollectionTrigger::Always),
942 )?;
943 let pt = idpu_identifier_mc_rx.pdu_triggering().unwrap();
944 ssc.add_ipdu_identifier(&idpu_identifier_mc_rx)?;
945 pt
946 };
947 pt_multicast_rx.create_pdu_port(ecu, CommunicationDirection::In)?;
949 Ok(())
950 }
951
952 #[must_use]
954 pub fn has_socket_connections(&self) -> bool {
955 if let Some(soad_config) = self.element().get_sub_element(ElementName::SoAdConfig) {
956 if let Some(connection_bundles) = soad_config.get_sub_element(ElementName::ConnectionBundles) {
957 if connection_bundles.sub_elements().count() > 0 {
959 return true;
960 }
961 }
962 if let Some(connections) = soad_config.get_sub_element(ElementName::Connections) {
963 return connections.sub_elements().count() > 0;
965 }
966 }
967 false
968 }
969}
970
971impl From<EthernetPhysicalChannel> for PhysicalChannel {
972 fn from(channel: EthernetPhysicalChannel) -> Self {
973 PhysicalChannel::Ethernet(channel)
974 }
975}
976
977impl AbstractPhysicalChannel for EthernetPhysicalChannel {
978 type CommunicationConnectorType = EthernetCommunicationConnector;
979}
980
981pub struct CommonServiceDiscoveryConfig<'a> {
987 pub multicast_rx_socket: &'a SocketAddress,
989 pub multicast_rx_pdu: &'a GeneralPurposePdu,
991 pub remote_socket: &'a SocketAddress,
993 pub prefer_static_socket_connections: bool,
996 pub ipdu_identifier_set: Option<&'a SocketConnectionIpduIdentifierSet>,
998 pub name_prefix: Option<&'a str>,
1000}
1001
1002#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1008pub struct StaticSocketConnection(Element);
1009abstraction_element!(StaticSocketConnection, StaticSocketConnection);
1010impl IdentifiableAbstractionElement for StaticSocketConnection {}
1011
1012impl StaticSocketConnection {
1013 pub(crate) fn new(
1014 name: &str,
1015 parent: &Element,
1016 remote_address: &SocketAddress,
1017 tcp_role: Option<TcpRole>,
1018 tcp_connect_timeout: Option<f64>,
1019 ) -> Result<Self, AutosarAbstractionError> {
1020 let connections = parent.get_or_create_sub_element(ElementName::StaticSocketConnections)?;
1021 let ssc_elem = connections.create_named_sub_element(ElementName::StaticSocketConnection, name)?;
1022
1023 let ssc = Self(ssc_elem);
1024
1025 ssc.set_remote_socket(remote_address)?;
1026 ssc.set_tcp_role(tcp_role)?;
1027 ssc.set_tcp_connect_timeout(tcp_connect_timeout)?;
1028
1029 Ok(ssc)
1030 }
1031
1032 pub fn socket_address(&self) -> Result<SocketAddress, AutosarAbstractionError> {
1034 let sa = self.element().named_parent()?.unwrap();
1035 SocketAddress::try_from(sa)
1036 }
1037
1038 pub fn set_remote_socket(&self, remote_socket: &SocketAddress) -> Result<(), AutosarAbstractionError> {
1040 self.element()
1041 .get_or_create_sub_element(ElementName::RemoteAddresss)?
1042 .get_or_create_sub_element(ElementName::SocketAddressRefConditional)?
1043 .get_or_create_sub_element(ElementName::SocketAddressRef)?
1044 .set_reference_target(remote_socket.element())?;
1045 Ok(())
1046 }
1047
1048 #[must_use]
1050 pub fn remote_socket(&self) -> Option<SocketAddress> {
1051 let remote_socket = self
1052 .element()
1053 .get_sub_element(ElementName::RemoteAddresss)?
1054 .get_sub_element(ElementName::SocketAddressRefConditional)?
1055 .get_sub_element(ElementName::SocketAddressRef)?
1056 .get_reference_target()
1057 .ok()?;
1058 SocketAddress::try_from(remote_socket).ok()
1059 }
1060
1061 pub fn add_ipdu_identifier(&self, identifier: &SoConIPduIdentifier) -> Result<(), AutosarAbstractionError> {
1063 let ipdu_identifiers = self.element().get_or_create_sub_element(ElementName::IPduIdentifiers)?;
1064 let scii = ipdu_identifiers
1065 .create_sub_element(ElementName::SoConIPduIdentifierRefConditional)?
1066 .create_sub_element(ElementName::SoConIPduIdentifierRef)?;
1067 scii.set_reference_target(identifier.element())?;
1068 Ok(())
1069 }
1070
1071 pub fn ipdu_identifiers(&self) -> impl Iterator<Item = SoConIPduIdentifier> + Send + use<> {
1073 self.element()
1074 .get_sub_element(ElementName::IPduIdentifiers)
1075 .into_iter()
1076 .flat_map(|elem| elem.sub_elements())
1077 .filter_map(|scirc: Element| {
1078 scirc
1079 .get_sub_element(ElementName::SoConIPduIdentifierRef)
1080 .and_then(|sciir| sciir.get_reference_target().ok())
1081 .and_then(|scii| SoConIPduIdentifier::try_from(scii).ok())
1082 })
1083 }
1084
1085 pub fn set_tcp_role(&self, role: Option<TcpRole>) -> Result<(), AutosarAbstractionError> {
1087 if let Some(role) = role {
1088 self.element()
1089 .get_or_create_sub_element(ElementName::TcpRole)?
1090 .set_character_data::<EnumItem>(role.into())?;
1091 } else {
1092 let _ = self.element().remove_sub_element_kind(ElementName::TcpRole);
1093 }
1094 Ok(())
1095 }
1096
1097 #[must_use]
1099 pub fn tcp_role(&self) -> Option<TcpRole> {
1100 self.element()
1101 .get_sub_element(ElementName::TcpRole)
1102 .and_then(|elem| elem.character_data())
1103 .and_then(|cdata| cdata.enum_value())
1104 .and_then(|enumitem| enumitem.try_into().ok())
1105 }
1106
1107 pub fn set_tcp_connect_timeout(&self, timeout: Option<f64>) -> Result<(), AutosarAbstractionError> {
1109 if let Some(timeout) = timeout {
1110 self.element()
1111 .get_or_create_sub_element(ElementName::TcpConnectTimeout)?
1112 .set_character_data(timeout)?;
1113 } else {
1114 let _ = self.element().remove_sub_element_kind(ElementName::TcpConnectTimeout);
1115 }
1116 Ok(())
1117 }
1118
1119 #[must_use]
1121 pub fn tcp_connect_timeout(&self) -> Option<f64> {
1122 self.element()
1123 .get_sub_element(ElementName::TcpConnectTimeout)
1124 .and_then(|elem| elem.character_data())
1125 .and_then(|cdata| cdata.parse_float())
1126 }
1127}
1128
1129#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1133pub struct SocketConnectionIpduIdentifierSet(Element);
1134abstraction_element!(SocketConnectionIpduIdentifierSet, SocketConnectionIpduIdentifierSet);
1135impl IdentifiableAbstractionElement for SocketConnectionIpduIdentifierSet {}
1136
1137impl SocketConnectionIpduIdentifierSet {
1138 pub(crate) fn new(name: &str, package: &ArPackage) -> Result<Self, AutosarAbstractionError> {
1143 let sci = package
1144 .element()
1145 .get_or_create_sub_element(ElementName::Elements)?
1146 .create_named_sub_element(ElementName::SocketConnectionIpduIdentifierSet, name)?;
1147 Ok(Self(sci))
1148 }
1149
1150 pub fn create_socon_ipdu_identifier<T: AbstractPdu>(
1152 &self,
1153 name: &str,
1154 pdu: &T,
1155 channel: &EthernetPhysicalChannel,
1156 header_id: Option<u64>,
1157 timeout: Option<f64>,
1158 collection_trigger: Option<PduCollectionTrigger>,
1159 ) -> Result<SoConIPduIdentifier, AutosarAbstractionError> {
1160 let ipdu_identifiers = self.element().get_or_create_sub_element(ElementName::IPduIdentifiers)?;
1161 SoConIPduIdentifier::new(
1162 name,
1163 &ipdu_identifiers,
1164 &pdu.clone().into(),
1165 channel,
1166 header_id,
1167 timeout,
1168 collection_trigger,
1169 )
1170 }
1171
1172 pub fn socon_ipdu_identifiers(&self) -> impl Iterator<Item = SoConIPduIdentifier> + Send + use<> {
1174 self.element()
1175 .get_sub_element(ElementName::IPduIdentifiers)
1176 .into_iter()
1177 .flat_map(|elem| elem.sub_elements())
1178 .filter_map(|elem| SoConIPduIdentifier::try_from(elem).ok())
1179 }
1180}
1181
1182#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1186pub struct SoConIPduIdentifier(Element);
1187abstraction_element!(SoConIPduIdentifier, SoConIPduIdentifier);
1188impl IdentifiableAbstractionElement for SoConIPduIdentifier {}
1189
1190impl SoConIPduIdentifier {
1191 pub const SD_HEADER_ID: u64 = 0xFFFF_8100;
1193
1194 pub(crate) fn new(
1196 name: &str,
1197 parent: &Element,
1198 pdu: &Pdu,
1199 channel: &EthernetPhysicalChannel,
1200 header_id: Option<u64>,
1201 timeout: Option<f64>,
1202 collection_trigger: Option<PduCollectionTrigger>,
1203 ) -> Result<Self, AutosarAbstractionError> {
1204 let scii = Self(parent.create_named_sub_element(ElementName::SoConIPduIdentifier, name)?);
1205 scii.set_pdu_internal(pdu, channel)?;
1206
1207 if let Some(header_id) = header_id {
1208 scii.set_header_id(header_id)?;
1209 }
1210 if let Some(timeout) = timeout {
1211 scii.set_timeout(timeout)?;
1212 }
1213 if let Some(collection_trigger) = collection_trigger {
1214 scii.set_collection_trigger(collection_trigger)?;
1215 }
1216 Ok(scii)
1217 }
1218
1219 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
1221 let opt_pdu_triggering = self.pdu_triggering();
1222
1223 AbstractionElement::remove(self, deep)?;
1224
1225 if let Some(pt) = opt_pdu_triggering {
1227 let _ = pt.remove(deep);
1228 }
1229
1230 Ok(())
1231 }
1232
1233 pub fn set_pdu<T: AbstractPdu>(
1235 &self,
1236 pdu: &T,
1237 channel: &EthernetPhysicalChannel,
1238 ) -> Result<(), AutosarAbstractionError> {
1239 let pdu: Pdu = pdu.clone().into();
1240 self.set_pdu_internal(&pdu, channel)
1241 }
1242
1243 fn set_pdu_internal(&self, pdu: &Pdu, channel: &EthernetPhysicalChannel) -> Result<(), AutosarAbstractionError> {
1244 if let Some(pt_ref_elem) = self.element().get_sub_element(ElementName::PduTriggeringRef)
1245 && let Ok(pt_old) = pt_ref_elem.get_reference_target()
1246 {
1247 let pt_old = PduTriggering::try_from(pt_old)?;
1248 if let Some(old_pdu) = pt_old.pdu() {
1249 if old_pdu == *pdu {
1250 return Ok(());
1251 }
1252 let _ = self.element().remove_sub_element(pt_ref_elem);
1255 let _ = pt_old.remove(false);
1256 }
1257 }
1258 let pt_new = PduTriggering::new(pdu, &PhysicalChannel::Ethernet(channel.clone()))?;
1259 self.element()
1260 .get_or_create_sub_element(ElementName::PduTriggeringRef)?
1261 .set_reference_target(pt_new.element())?;
1262 Ok(())
1263 }
1264
1265 pub fn set_header_id(&self, header_id: u64) -> Result<(), AutosarAbstractionError> {
1267 self.element()
1268 .get_or_create_sub_element(ElementName::HeaderId)?
1269 .set_character_data(header_id)?;
1270 Ok(())
1271 }
1272
1273 pub fn set_timeout(&self, timeout: f64) -> Result<(), AutosarAbstractionError> {
1275 self.element()
1276 .get_or_create_sub_element(ElementName::PduCollectionPduTimeout)?
1277 .set_character_data(timeout)?;
1278 Ok(())
1279 }
1280
1281 pub fn set_collection_trigger(&self, trigger: PduCollectionTrigger) -> Result<(), AutosarAbstractionError> {
1283 self.element()
1284 .get_or_create_sub_element(ElementName::PduCollectionTrigger)?
1285 .set_character_data::<EnumItem>(trigger.into())?;
1286 Ok(())
1287 }
1288
1289 #[must_use]
1291 pub fn pdu_triggering(&self) -> Option<PduTriggering> {
1292 let pt = self
1293 .element()
1294 .get_sub_element(ElementName::PduTriggeringRef)?
1295 .get_reference_target()
1296 .ok()?;
1297 PduTriggering::try_from(pt).ok()
1298 }
1299
1300 #[must_use]
1302 pub fn header_id(&self) -> Option<u64> {
1303 self.element()
1304 .get_sub_element(ElementName::HeaderId)?
1305 .character_data()?
1306 .parse_integer()
1307 }
1308
1309 #[must_use]
1311 pub fn timeout(&self) -> Option<f64> {
1312 self.element()
1313 .get_sub_element(ElementName::PduCollectionPduTimeout)?
1314 .character_data()?
1315 .float_value()
1316 }
1317
1318 #[must_use]
1320 pub fn collection_trigger(&self) -> Option<PduCollectionTrigger> {
1321 self.element()
1322 .get_sub_element(ElementName::PduCollectionTrigger)?
1323 .character_data()?
1324 .enum_value()?
1325 .try_into()
1326 .ok()
1327 }
1328}
1329
1330#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1334pub enum TcpRole {
1335 Connect,
1337 Listen,
1339}
1340
1341impl TryFrom<EnumItem> for TcpRole {
1342 type Error = AutosarAbstractionError;
1343
1344 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
1345 match value {
1346 EnumItem::Listen => Ok(Self::Listen),
1347 EnumItem::Connect => Ok(Self::Connect),
1348
1349 _ => Err(AutosarAbstractionError::ValueConversionError {
1350 value: value.to_string(),
1351 dest: "TcpRole".to_string(),
1352 }),
1353 }
1354 }
1355}
1356
1357impl From<TcpRole> for EnumItem {
1358 fn from(value: TcpRole) -> Self {
1359 match value {
1360 TcpRole::Listen => EnumItem::Listen,
1361 TcpRole::Connect => EnumItem::Connect,
1362 }
1363 }
1364}
1365
1366#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1370pub enum EventGroupControlType {
1371 ActivationAndTriggerUnicast,
1373 ActivationMulticast,
1375 ActivationUnicast,
1377 TriggerUnicast,
1379}
1380
1381impl From<EventGroupControlType> for EnumItem {
1382 fn from(value: EventGroupControlType) -> Self {
1383 match value {
1384 EventGroupControlType::ActivationAndTriggerUnicast => EnumItem::ActivationAndTriggerUnicast,
1385 EventGroupControlType::ActivationMulticast => EnumItem::ActivationMulticast,
1386 EventGroupControlType::ActivationUnicast => EnumItem::ActivationUnicast,
1387 EventGroupControlType::TriggerUnicast => EnumItem::TriggerUnicast,
1388 }
1389 }
1390}
1391
1392impl TryFrom<EnumItem> for EventGroupControlType {
1393 type Error = AutosarAbstractionError;
1394
1395 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
1396 match value {
1397 EnumItem::ActivationAndTriggerUnicast => Ok(Self::ActivationAndTriggerUnicast),
1398 EnumItem::ActivationMulticast => Ok(Self::ActivationMulticast),
1399 EnumItem::ActivationUnicast => Ok(Self::ActivationUnicast),
1400 EnumItem::TriggerUnicast => Ok(Self::TriggerUnicast),
1401
1402 _ => Err(AutosarAbstractionError::ValueConversionError {
1403 value: value.to_string(),
1404 dest: "EventGroupControlType".to_string(),
1405 }),
1406 }
1407 }
1408}
1409
1410#[cfg(test)]
1413mod test {
1414 use super::*;
1415 use crate::{ArPackage, AutosarModelAbstraction, System, SystemCategory, communication::GeneralPurposePduCategory};
1416 use autosar_data::AutosarVersion;
1417
1418 #[test]
1419 fn channel_basic() {
1420 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00044);
1421 let pkg = model.get_or_create_package("/test").unwrap();
1422 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
1423 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
1424 let channel = cluster.create_physical_channel("Channel", None).unwrap();
1425
1426 let wrapped_channel: PhysicalChannel = channel.clone().into();
1427 assert_eq!(wrapped_channel, PhysicalChannel::Ethernet(channel));
1428 }
1429
1430 #[test]
1431 fn channel_network_endpoint() {
1432 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00044);
1434 let pkg = model.get_or_create_package("/test").unwrap();
1435 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
1436 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
1437 let channel = cluster.create_physical_channel("Channel", None).unwrap();
1438
1439 let endpoint = channel
1441 .create_network_endpoint(
1442 "Endpoint",
1443 NetworkEndpointAddress::IPv4 {
1444 address: Some("192.168.0.1".to_string()),
1445 address_source: None,
1446 default_gateway: None,
1447 network_mask: None,
1448 },
1449 None,
1450 )
1451 .unwrap();
1452 assert_eq!(channel.network_endpoints().next().unwrap(), endpoint);
1453
1454 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
1458 let result = channel.create_network_endpoint(
1459 "Endpoint1",
1460 NetworkEndpointAddress::IPv4 {
1461 address: Some("192.168.0.2".to_string()),
1462 address_source: None,
1463 default_gateway: None,
1464 network_mask: None,
1465 },
1466 Some(&ecu),
1467 );
1468 assert!(result.is_err());
1469 assert_eq!(channel.network_endpoints().next().unwrap(), endpoint);
1470
1471 let ethernet_controller = ecu
1473 .create_ethernet_communication_controller("Controller", Some("01:23:45:ab:cd:ef".to_string()))
1474 .unwrap();
1475 ethernet_controller
1476 .connect_physical_channel("connection", &channel)
1477 .unwrap();
1478 let endpoint = channel
1479 .create_network_endpoint(
1480 "Endpoint2",
1481 NetworkEndpointAddress::IPv4 {
1482 address: Some("192.168.0.2".to_string()),
1483 address_source: None,
1484 default_gateway: None,
1485 network_mask: None,
1486 },
1487 Some(&ecu),
1488 )
1489 .unwrap();
1490 assert_eq!(channel.network_endpoints().last().unwrap(), endpoint);
1491 assert_eq!(channel.network_endpoints().count(), 2);
1492 }
1493
1494 #[test]
1495 fn channel_vlan() {
1496 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
1497 let pkg = model.get_or_create_package("/test").unwrap();
1498 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
1499 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
1500
1501 let channel = cluster.create_physical_channel("channel_name", None).unwrap();
1502 let c2 = channel.cluster().unwrap();
1503 assert_eq!(cluster, c2);
1504
1505 let vi = channel.vlan_info();
1506 assert!(vi.is_none());
1507
1508 let elem_vlan = channel
1509 .element()
1510 .create_named_sub_element(ElementName::Vlan, "VLAN_1")
1511 .unwrap();
1512 let vi = channel.vlan_info();
1513 assert!(vi.is_none());
1514
1515 let elem_vlanid = elem_vlan.create_sub_element(ElementName::VlanIdentifier).unwrap();
1516 let vi = channel.vlan_info();
1517 assert!(vi.is_none());
1518
1519 elem_vlanid.set_character_data(1).unwrap();
1520 let vi = channel.vlan_info().unwrap();
1521 assert_eq!(vi.vlan_id, 1);
1522 }
1523
1524 #[test]
1525 fn sd_configuration_old() {
1526 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00044);
1528 let pkg = model.get_or_create_package("/test").unwrap();
1529 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
1530 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
1531 let channel = cluster.create_physical_channel("Channel", None).unwrap();
1532
1533 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
1534 let controller = ecu
1535 .create_ethernet_communication_controller("EthController", None)
1536 .unwrap();
1537 controller.connect_physical_channel("connection", &channel).unwrap();
1538
1539 let (
1540 unicast_socket,
1541 multicast_rx_socket,
1542 remote_anyaddr_socket,
1543 unicast_rx_pdu,
1544 unicast_tx_pdu,
1545 multicast_rx_pdu,
1546 ) = prepare_sd_config_items(&pkg, &system, &channel, &ecu);
1547
1548 let common_config = CommonServiceDiscoveryConfig {
1549 multicast_rx_socket: &multicast_rx_socket,
1550 multicast_rx_pdu: &multicast_rx_pdu,
1551 remote_socket: &remote_anyaddr_socket,
1552 name_prefix: None,
1553 prefer_static_socket_connections: false,
1554 ipdu_identifier_set: None,
1555 };
1556
1557 let result = channel.configure_service_discovery_for_ecu(
1558 &ecu,
1559 &unicast_socket,
1560 &unicast_rx_pdu,
1561 &unicast_tx_pdu,
1562 &common_config,
1563 );
1564 assert!(result.is_ok());
1565
1566 assert_eq!(channel.socket_connection_bundles().count(), 2);
1567 assert!(channel.socket_connection_bundles().any(|scb| {
1568 scb.server_port().is_some_and(|sp| sp == unicast_socket)
1569 && scb.bundled_connections().any(|sc| {
1570 sc.client_ip_addr_from_connection_request() == Some(true)
1571 && sc.client_port().is_some_and(|cp| &cp == common_config.remote_socket)
1572 && sc.pdu_triggerings().count() == 2
1573 })
1574 }));
1575 assert!(channel.socket_connection_bundles().any(|scb| {
1576 scb.server_port()
1577 .is_some_and(|sp| &sp == common_config.multicast_rx_socket)
1578 && scb.bundled_connections().any(|sc| {
1579 sc.client_ip_addr_from_connection_request() == Some(true)
1580 && sc.client_port().is_some_and(|cp| &cp == common_config.remote_socket)
1581 && sc.pdu_triggerings().count() == 1
1582 })
1583 }));
1584
1585 let result = channel.configure_service_discovery_for_ecu(
1587 &ecu,
1588 &unicast_socket,
1589 &unicast_rx_pdu,
1590 &unicast_tx_pdu,
1591 &common_config,
1592 );
1593 assert!(result.is_ok());
1594 assert_eq!(channel.socket_connection_bundles().count(), 2);
1595 }
1596
1597 #[test]
1598 fn sd_configuration_new() {
1599 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00053);
1600 let pkg = model.get_or_create_package("/test").unwrap();
1601 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
1602 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
1603 let channel = cluster.create_physical_channel("Channel", None).unwrap();
1604
1605 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
1606 let controller = ecu
1607 .create_ethernet_communication_controller("EthController", None)
1608 .unwrap();
1609 controller.connect_physical_channel("connection", &channel).unwrap();
1610
1611 let (
1612 unicast_socket,
1613 multicast_rx_socket,
1614 remote_anyaddr_socket,
1615 unicast_rx_pdu,
1616 unicast_tx_pdu,
1617 multicast_rx_pdu,
1618 ) = prepare_sd_config_items(&pkg, &system, &channel, &ecu);
1619 let ipdu_identifier_set = system
1620 .create_socket_connection_ipdu_identifier_set("IpduIdentifierSet", &pkg)
1621 .unwrap();
1622
1623 let common_config = CommonServiceDiscoveryConfig {
1624 multicast_rx_socket: &multicast_rx_socket,
1625 multicast_rx_pdu: &multicast_rx_pdu,
1626 remote_socket: &remote_anyaddr_socket,
1627 name_prefix: None,
1628 prefer_static_socket_connections: true,
1629 ipdu_identifier_set: Some(&ipdu_identifier_set),
1630 };
1631
1632 let result = channel.configure_service_discovery_for_ecu(
1633 &ecu,
1634 &unicast_socket,
1635 &unicast_rx_pdu,
1636 &unicast_tx_pdu,
1637 &common_config,
1638 );
1639 assert!(result.is_ok());
1640
1641 assert!(unicast_socket.static_socket_connections().count() == 1);
1643 assert!(unicast_socket.static_socket_connections().any(|ssc| {
1644 ssc.remote_socket().is_some_and(|rs| &rs == common_config.remote_socket)
1645 && ssc.ipdu_identifiers().count() == 2
1646 }));
1647
1648 assert!(multicast_rx_socket.static_socket_connections().count() == 1);
1649 assert!(multicast_rx_socket.static_socket_connections().any(|ssc| {
1650 ssc.remote_socket().is_some_and(|rs| &rs == common_config.remote_socket)
1651 && ssc.ipdu_identifiers().count() == 1
1652 }));
1653
1654 let result = channel.configure_service_discovery_for_ecu(
1656 &ecu,
1657 &unicast_socket,
1658 &unicast_rx_pdu,
1659 &unicast_tx_pdu,
1660 &common_config,
1661 );
1662 assert!(result.is_ok());
1663
1664 assert!(unicast_socket.static_socket_connections().count() == 1);
1665 assert!(multicast_rx_socket.static_socket_connections().count() == 1);
1666 }
1667
1668 fn prepare_sd_config_items(
1669 pkg: &ArPackage,
1670 system: &System,
1671 channel: &EthernetPhysicalChannel,
1672 ecu: &EcuInstance,
1673 ) -> (
1674 SocketAddress,
1675 SocketAddress,
1676 SocketAddress,
1677 GeneralPurposePdu,
1678 GeneralPurposePdu,
1679 GeneralPurposePdu,
1680 ) {
1681 let network_address = NetworkEndpointAddress::IPv4 {
1682 address: Some("192.168.0.1".to_string()),
1683 address_source: Some(IPv4AddressSource::Fixed),
1684 default_gateway: Some("192.168.0.200".to_string()),
1685 network_mask: Some("255.255.255.0".to_string()),
1686 };
1687 let network_endpoint = channel
1688 .create_network_endpoint("local_endpoint", network_address, None)
1689 .unwrap();
1690 let unicast_socket = channel
1691 .create_socket_address(
1692 "UnicastSocket",
1693 &network_endpoint,
1694 &TpConfig::UdpTp {
1695 port_number: Some(30490),
1696 port_dynamically_assigned: None,
1697 },
1698 SocketAddressType::Unicast(Some(ecu.clone())),
1699 )
1700 .unwrap();
1701 let multicast_rx_endpoint = channel
1702 .create_network_endpoint(
1703 "MulticastEndpoint",
1704 NetworkEndpointAddress::IPv4 {
1705 address: Some("239.0.0.1".to_string()),
1706 address_source: Some(IPv4AddressSource::Fixed),
1707 default_gateway: None,
1708 network_mask: None,
1709 },
1710 None,
1711 )
1712 .unwrap();
1713 let multicast_rx_socket = channel
1714 .create_socket_address(
1715 "MulticastSocket",
1716 &multicast_rx_endpoint,
1717 &TpConfig::UdpTp {
1718 port_number: Some(30490),
1719 port_dynamically_assigned: None,
1720 },
1721 SocketAddressType::Multicast(vec![ecu.clone()]),
1722 )
1723 .unwrap();
1724 let remote_anyaddr_endpoint = channel
1725 .create_network_endpoint(
1726 "RemoteEndpoint",
1727 NetworkEndpointAddress::IPv4 {
1728 address: Some("ANY".to_string()),
1729 address_source: None,
1730 default_gateway: None,
1731 network_mask: None,
1732 },
1733 None,
1734 )
1735 .unwrap();
1736 let remote_anyaddr_socket = channel
1737 .create_socket_address(
1738 "RemoteSocket",
1739 &remote_anyaddr_endpoint,
1740 &TpConfig::UdpTp {
1741 port_number: None,
1742 port_dynamically_assigned: Some(true),
1743 },
1744 SocketAddressType::Unicast(None),
1745 )
1746 .unwrap();
1747 let unicast_rx_pdu = system
1748 .create_general_purpose_pdu("UnicastRxPdu", pkg, 0, GeneralPurposePduCategory::Sd)
1749 .unwrap();
1750 let unicast_tx_pdu = system
1751 .create_general_purpose_pdu("UnicastTxPdu", pkg, 0, GeneralPurposePduCategory::Sd)
1752 .unwrap();
1753 let multicast_rx_pdu = system
1754 .create_general_purpose_pdu("MulticastRxPdu", pkg, 0, GeneralPurposePduCategory::Sd)
1755 .unwrap();
1756 (
1757 unicast_socket,
1758 multicast_rx_socket,
1759 remote_anyaddr_socket,
1760 unicast_rx_pdu,
1761 unicast_tx_pdu,
1762 multicast_rx_pdu,
1763 )
1764 }
1765
1766 #[test]
1767 fn socon_ipdu_identifier() {
1768 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1769 let pkg = model.get_or_create_package("/test").unwrap();
1770 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
1771 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
1772 let channel = cluster.create_physical_channel("Channel", None).unwrap();
1773 let ecu = system.create_ecu_instance("ECU", &pkg).unwrap();
1774 let ipdu_identifier_set = system
1775 .create_socket_connection_ipdu_identifier_set("IpduIdentifierSet", &pkg)
1776 .unwrap();
1777 let pdu = system
1778 .create_general_purpose_pdu("Pdu", &pkg, 1, GeneralPurposePduCategory::Sd)
1779 .unwrap();
1780 let pdu2 = system
1781 .create_general_purpose_pdu("Pdu2", &pkg, 2, GeneralPurposePduCategory::Sd)
1782 .unwrap();
1783 let controller = ecu
1784 .create_ethernet_communication_controller("Controller", Some("01:23:45:ab:cd:ef".to_string()))
1785 .unwrap();
1786 controller.connect_physical_channel("connection", &channel).unwrap();
1787
1788 let socon_ipdu_identifier = ipdu_identifier_set
1789 .create_socon_ipdu_identifier(
1790 "SoConIPduIdentifier",
1791 &pdu,
1792 &channel,
1793 Some(SoConIPduIdentifier::SD_HEADER_ID),
1794 Some(0.1),
1795 Some(PduCollectionTrigger::Always),
1796 )
1797 .unwrap();
1798 assert_eq!(
1799 socon_ipdu_identifier.pdu_triggering().unwrap().pdu().unwrap(),
1800 pdu.into()
1801 );
1802 assert_eq!(
1803 socon_ipdu_identifier.header_id().unwrap(),
1804 SoConIPduIdentifier::SD_HEADER_ID
1805 );
1806 assert_eq!(socon_ipdu_identifier.timeout().unwrap(), 0.1);
1807 assert_eq!(
1808 socon_ipdu_identifier.collection_trigger().unwrap(),
1809 PduCollectionTrigger::Always
1810 );
1811
1812 socon_ipdu_identifier.set_pdu(&pdu2, &channel).unwrap();
1813 assert_eq!(
1814 socon_ipdu_identifier.pdu_triggering().unwrap().pdu().unwrap(),
1815 pdu2.into()
1816 );
1817 socon_ipdu_identifier.set_timeout(0.2).unwrap();
1818 assert_eq!(socon_ipdu_identifier.timeout().unwrap(), 0.2);
1819 socon_ipdu_identifier
1820 .set_collection_trigger(PduCollectionTrigger::Never)
1821 .unwrap();
1822 assert_eq!(
1823 socon_ipdu_identifier.collection_trigger().unwrap(),
1824 PduCollectionTrigger::Never
1825 );
1826 socon_ipdu_identifier.set_header_id(0x1234).unwrap();
1827 assert_eq!(socon_ipdu_identifier.header_id().unwrap(), 0x1234);
1828 }
1829
1830 #[test]
1831 pub fn static_socket_connection() {
1832 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1833 let pkg = model.get_or_create_package("/test").unwrap();
1834 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
1835 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
1836 let channel = cluster.create_physical_channel("Channel", None).unwrap();
1837
1838 let remote_address = NetworkEndpointAddress::IPv4 {
1840 address: Some("192.168.0.1".to_string()),
1841 address_source: Some(IPv4AddressSource::Fixed),
1842 default_gateway: None,
1843 network_mask: None,
1844 };
1845 let remote_endpoint = channel
1846 .create_network_endpoint("RemoteAddress", remote_address, None)
1847 .unwrap();
1848 let remote_socket = channel
1849 .create_socket_address(
1850 "RemoteSocket",
1851 &remote_endpoint,
1852 &TpConfig::UdpTp {
1853 port_number: Some(12345),
1854 port_dynamically_assigned: None,
1855 },
1856 SocketAddressType::Unicast(None),
1857 )
1858 .unwrap();
1859 let local_address = NetworkEndpointAddress::IPv4 {
1860 address: Some("192.168.0.2".to_string()),
1861 address_source: Some(IPv4AddressSource::Fixed),
1862 default_gateway: None,
1863 network_mask: None,
1864 };
1865 let local_endpoint = channel
1866 .create_network_endpoint("LocalAddress", local_address, None)
1867 .unwrap();
1868 let local_socket = channel
1869 .create_socket_address(
1870 "LocalSocket",
1871 &local_endpoint,
1872 &TpConfig::UdpTp {
1873 port_number: Some(12346),
1874 port_dynamically_assigned: None,
1875 },
1876 SocketAddressType::Unicast(None),
1877 )
1878 .unwrap();
1879 let ssc = local_socket
1880 .create_static_socket_connection("ssc", &remote_socket, None, None)
1881 .unwrap();
1882 assert_eq!(ssc.remote_socket().unwrap(), remote_socket);
1883 assert_eq!(ssc.tcp_role(), None);
1884 ssc.set_tcp_role(Some(TcpRole::Connect)).unwrap();
1885 assert_eq!(ssc.tcp_role().unwrap(), TcpRole::Connect);
1886 ssc.set_tcp_connect_timeout(Some(0.3333)).unwrap();
1887 assert_eq!(ssc.tcp_connect_timeout().unwrap(), 0.3333);
1888
1889 assert_eq!(ssc.ipdu_identifiers().count(), 0);
1891 let ipdu_identifier_set = system
1892 .create_socket_connection_ipdu_identifier_set("IpduIdentifierSet", &pkg)
1893 .unwrap();
1894 let pdu = GeneralPurposePdu::new("Pdu", &pkg, 0, GeneralPurposePduCategory::Sd).unwrap();
1895 let socon_ipdu_identifier = ipdu_identifier_set
1896 .create_socon_ipdu_identifier(
1897 "SoConIPduIdentifier",
1898 &pdu,
1899 &channel,
1900 Some(SoConIPduIdentifier::SD_HEADER_ID),
1901 Some(0.1),
1902 Some(PduCollectionTrigger::Always),
1903 )
1904 .unwrap();
1905 ssc.add_ipdu_identifier(&socon_ipdu_identifier).unwrap();
1906 assert_eq!(ssc.ipdu_identifiers().count(), 1);
1907 assert_eq!(ssc.ipdu_identifiers().next().unwrap(), socon_ipdu_identifier);
1908 assert_eq!(ssc.socket_address().unwrap(), local_socket);
1909 }
1910
1911 #[test]
1912 fn remove_channel() {
1913 let model = AutosarModelAbstraction::create("filename", AutosarVersion::LATEST);
1914 let pkg = model.get_or_create_package("/test").unwrap();
1915 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
1916 let cluster = system.create_ethernet_cluster("EthCluster", &pkg).unwrap();
1917 let channel = cluster.create_physical_channel("Channel", None).unwrap();
1918
1919 let remote_address = NetworkEndpointAddress::IPv4 {
1920 address: Some("192.168.0.1".to_string()),
1921 address_source: Some(IPv4AddressSource::Fixed),
1922 default_gateway: None,
1923 network_mask: None,
1924 };
1925 let remote_endpoint = channel
1926 .create_network_endpoint("RemoteAddress", remote_address, None)
1927 .unwrap();
1928 let remote_socket = channel
1929 .create_socket_address(
1930 "RemoteSocket",
1931 &remote_endpoint,
1932 &TpConfig::UdpTp {
1933 port_number: Some(12345),
1934 port_dynamically_assigned: None,
1935 },
1936 SocketAddressType::Unicast(None),
1937 )
1938 .unwrap();
1939 let local_address = NetworkEndpointAddress::IPv4 {
1940 address: Some("192.168.0.2".to_string()),
1941 address_source: Some(IPv4AddressSource::Fixed),
1942 default_gateway: None,
1943 network_mask: None,
1944 };
1945 let local_endpoint = channel
1946 .create_network_endpoint("LocalAddress", local_address, None)
1947 .unwrap();
1948 let local_socket = channel
1949 .create_socket_address(
1950 "LocalSocket",
1951 &local_endpoint,
1952 &TpConfig::UdpTp {
1953 port_number: Some(12346),
1954 port_dynamically_assigned: None,
1955 },
1956 SocketAddressType::Unicast(None),
1957 )
1958 .unwrap();
1959
1960 let scb = channel
1961 .create_socket_connection_bundle("SocketConnectionBundle", &local_socket)
1962 .unwrap();
1963 let sc = scb.create_bundled_connection(&remote_socket).unwrap();
1964
1965 let isignal_ipdu = system.create_isignal_ipdu("IPdu", &pkg, 0).unwrap();
1966 sc.create_socket_connection_ipdu_identifier(&isignal_ipdu, 0xdeadbeef, None, None)
1967 .unwrap();
1968
1969 assert_eq!(channel.socket_connection_bundles().count(), 1);
1970 assert_eq!(channel.socket_addresses().count(), 2);
1971 assert_eq!(channel.network_endpoints().count(), 2);
1972 assert_eq!(channel.pdu_triggerings().count(), 1);
1973
1974 channel.remove(true).unwrap();
1975
1976 assert_eq!(cluster.physical_channels().count(), 0);
1977
1978 assert!(isignal_ipdu.element().parent().is_err());
1980 }
1981}