Skip to content

Commit

Permalink
feat(nm): ipv6 status information retrieval (#4806)
Browse files Browse the repository at this point in the history
* feat: add ip6 status retrival code

* fix: use correct property for ipv6 dns retrival

* fix: reintroduce forgotten check

* fix: dumb mistake

* feat: add dns address conversion

* test: fix nm tests for ipv6 status

* test: add NMStatusConverterTest

* style: add copyright headers

* fix: leftover test

* fix: remove unnecessary argument matchers

* test: use improved exception handling recipe

* test: add initial tests for ipv6 status

* refactor: thenNoExceptionIsThrown -> thenNoExceptionOccurred

* test: add complete test for ipv6 status on ethernet interface

* test: add multiple dns test

* fix(nm): correctly handle multiple dns

* test: add test with wrong ip address

* test: support multiple ipv4 address checking

* test: support multiple ipv6 address checking

* test: add test for when both ipv4 and ipv6 are active

* refactor(nm): setIPX method now support both ip versions

* refactor: small change for conversion List<Byte> to byte[]
  • Loading branch information
mattdibi authored Aug 17, 2023
1 parent f0a99ec commit 0a9ceb6
Show file tree
Hide file tree
Showing 4 changed files with 887 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public class NMDbusConnector {

private static final String NM_DEVICE_PROPERTY_INTERFACE = "Interface";
private static final String NM_DEVICE_PROPERTY_IP4CONFIG = "Ip4Config";
private static final String NM_DEVICE_PROPERTY_IP6CONFIG = "Ip6Config";

private static final List<NMDeviceType> CONFIGURATION_SUPPORTED_DEVICE_TYPES = Arrays.asList(
NMDeviceType.NM_DEVICE_TYPE_ETHERNET, NMDeviceType.NM_DEVICE_TYPE_WIFI, NMDeviceType.NM_DEVICE_TYPE_MODEM);
Expand Down Expand Up @@ -210,6 +211,14 @@ public synchronized NetworkInterfaceStatus getInterfaceStatus(String interfaceId
this.dbusConnection.getRemoteObject(NM_BUS_NAME, ip4configPath.getPath(), Properties.class));
}

DBusPath ip6configPath = deviceProperties.Get(NM_DEVICE_BUS_NAME, NM_DEVICE_PROPERTY_IP6CONFIG);
Optional<Properties> ip6configProperties = Optional.empty();

if (!ip6configPath.getPath().equals("/")) {
ip6configProperties = Optional.of(
this.dbusConnection.getRemoteObject(NM_BUS_NAME, ip6configPath.getPath(), Properties.class));
}

if (!STATUS_SUPPORTED_DEVICE_TYPES.contains(deviceType)) {
logger.warn("Device \"{}\" of type \"{}\" currently not supported", interfaceId, deviceType);
return null;
Expand All @@ -226,26 +235,26 @@ public synchronized NetworkInterfaceStatus getInterfaceStatus(String interfaceId
Optional.of(wiredDeviceProperties), NMDeviceType.NM_DEVICE_TYPE_ETHERNET);

networkInterfaceStatus = NMStatusConverter.buildEthernetStatus(interfaceId, ethernetPropertiesWrapper,
ip4configProperties);
ip4configProperties, ip6configProperties);
break;
case NM_DEVICE_TYPE_LOOPBACK:
DevicePropertiesWrapper loopbackPropertiesWrapper = new DevicePropertiesWrapper(deviceProperties,
Optional.empty(), NMDeviceType.NM_DEVICE_TYPE_LOOPBACK);

networkInterfaceStatus = NMStatusConverter.buildLoopbackStatus(interfaceId, loopbackPropertiesWrapper,
ip4configProperties);
ip4configProperties, ip6configProperties);
break;
case NM_DEVICE_TYPE_WIFI:
if (recompute) {
wpaSupplicant.syncScan(interfaceId, MAX_SCAN_TIME_SECONDS);
}

networkInterfaceStatus = createWirelessStatus(interfaceId, commandExecutorService, device.get(),
deviceProperties, ip4configProperties);
deviceProperties, ip4configProperties, ip6configProperties);
break;
case NM_DEVICE_TYPE_MODEM:
networkInterfaceStatus = createModemStatus(interfaceId, device.get(), deviceProperties,
ip4configProperties);
ip4configProperties, ip6configProperties);
break;
default:
break;
Expand All @@ -255,7 +264,7 @@ public synchronized NetworkInterfaceStatus getInterfaceStatus(String interfaceId
}

private NetworkInterfaceStatus createModemStatus(String interfaceId, Device device, Properties deviceProperties,
Optional<Properties> ip4configProperties) throws DBusException {
Optional<Properties> ip4configProperties, Optional<Properties> ip6configProperties) throws DBusException {
NetworkInterfaceStatus networkInterfaceStatus;
Optional<String> modemPath = this.networkManager.getModemManagerDbusPath(device.getObjectPath());
Optional<Properties> modemDeviceProperties = Optional.empty();
Expand All @@ -272,13 +281,14 @@ private NetworkInterfaceStatus createModemStatus(String interfaceId, Device devi
DevicePropertiesWrapper modemPropertiesWrapper = new DevicePropertiesWrapper(deviceProperties,
modemDeviceProperties, NMDeviceType.NM_DEVICE_TYPE_MODEM);
networkInterfaceStatus = NMStatusConverter.buildModemStatus(interfaceId, modemPropertiesWrapper,
ip4configProperties, simProperties, bearerProperties);
ip4configProperties, ip6configProperties, simProperties, bearerProperties);
return networkInterfaceStatus;
}

private NetworkInterfaceStatus createWirelessStatus(String interfaceId,
CommandExecutorService commandExecutorService, Device device, Properties deviceProperties,
Optional<Properties> ip4configProperties) throws DBusException, KuraException {
Optional<Properties> ip4configProperties, Optional<Properties> ip6configProperties)
throws DBusException, KuraException {
NetworkInterfaceStatus networkInterfaceStatus = null;
Wireless wirelessDevice = this.dbusConnection.getRemoteObject(NM_BUS_NAME, device.getObjectPath(),
Wireless.class);
Expand All @@ -300,7 +310,7 @@ private NetworkInterfaceStatus createWirelessStatus(String interfaceId,
Optional.of(wirelessDeviceProperties), NMDeviceType.NM_DEVICE_TYPE_WIFI);

networkInterfaceStatus = NMStatusConverter.buildWirelessStatus(interfaceId, wirelessPropertiesWrapper,
ip4configProperties, new AccessPointsProperties(activeAccessPoint, accessPoints),
ip4configProperties, ip6configProperties, new AccessPointsProperties(activeAccessPoint, accessPoints),
new SupportedChannelsProperties(countryCode, supportedChannels));
return networkInterfaceStatus;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.Set;

import org.eclipse.kura.net.IP4Address;
import org.eclipse.kura.net.IP6Address;
import org.eclipse.kura.net.IPAddress;
import org.eclipse.kura.net.modem.ModemConnectionType;
import org.eclipse.kura.net.status.NetworkInterfaceIpAddress;
Expand Down Expand Up @@ -90,6 +91,7 @@ public class NMStatusConverter {
private static final String NM_DEVICE_WIRED_BUS_NAME = "org.freedesktop.NetworkManager.Device.Wired";
private static final String NM_ACCESSPOINT_BUS_NAME = "org.freedesktop.NetworkManager.AccessPoint";
private static final String NM_IP4CONFIG_BUS_NAME = "org.freedesktop.NetworkManager.IP4Config";
private static final String NM_IP6CONFIG_BUS_NAME = "org.freedesktop.NetworkManager.IP6Config";
private static final String NM_DEVICE_PROPERTY_HW_ADDRESS = "HwAddress";
private static final String MM_MODEM_BUS_NAME = "org.freedesktop.ModemManager1.Modem";
private static final String MM_SIM_BUS_NAME = "org.freedesktop.ModemManager1.Sim";
Expand All @@ -105,7 +107,8 @@ private NMStatusConverter() {
}

public static NetworkInterfaceStatus buildEthernetStatus(String interfaceId,
DevicePropertiesWrapper devicePropertiesWrapper, Optional<Properties> ip4configProperties) {
DevicePropertiesWrapper devicePropertiesWrapper, Optional<Properties> ip4configProperties,
Optional<Properties> ip6configProperties) {

EthernetInterfaceStatusBuilder builder = EthernetInterfaceStatus.builder();
builder.withInterfaceId(interfaceId).withInterfaceName(interfaceId).withVirtual(false);
Expand All @@ -117,13 +120,15 @@ public static NetworkInterfaceStatus buildEthernetStatus(String interfaceId,

setDeviceStatus(builder, devicePropertiesWrapper);
setIP4Status(builder, ip4configProperties);
setIP6Status(builder, ip6configProperties);

return builder.build();

}

public static NetworkInterfaceStatus buildLoopbackStatus(String interfaceId,
DevicePropertiesWrapper devicePropertiesWrapper, Optional<Properties> ip4configProperties) {
DevicePropertiesWrapper devicePropertiesWrapper, Optional<Properties> ip4configProperties,
Optional<Properties> ip6configProperties) {
LoopbackInterfaceStatusBuilder builder = LoopbackInterfaceStatus.builder();
builder.withInterfaceId(interfaceId).withInterfaceName(interfaceId).withVirtual(true);

Expand All @@ -133,13 +138,15 @@ public static NetworkInterfaceStatus buildLoopbackStatus(String interfaceId,

setDeviceStatus(builder, devicePropertiesWrapper);
setIP4Status(builder, ip4configProperties);
setIP6Status(builder, ip6configProperties);

return builder.build();
}

public static NetworkInterfaceStatus buildWirelessStatus(String interfaceId,
DevicePropertiesWrapper devicePropertiesWrapper, Optional<Properties> ip4configProperties,
AccessPointsProperties accessPointsProperties, SupportedChannelsProperties supportedChannelsProperties) {
Optional<Properties> ip6configProperties, AccessPointsProperties accessPointsProperties,
SupportedChannelsProperties supportedChannelsProperties) {
WifiInterfaceStatusBuilder builder = WifiInterfaceStatus.builder();
builder.withInterfaceId(interfaceId).withInterfaceName(interfaceId).withVirtual(false);

Expand All @@ -149,6 +156,7 @@ public static NetworkInterfaceStatus buildWirelessStatus(String interfaceId,

setDeviceStatus(builder, devicePropertiesWrapper);
setIP4Status(builder, ip4configProperties);
setIP6Status(builder, ip6configProperties);
setWifiStatus(builder, devicePropertiesWrapper.getDeviceSpecificProperties(),
accessPointsProperties.getActiveAccessPoint(), accessPointsProperties.getAvailableAccessPoints(),
supportedChannelsProperties.getCountryCode(), supportedChannelsProperties.getSupportedChannels());
Expand All @@ -172,7 +180,8 @@ private static void setDeviceStatus(NetworkInterfaceStatusBuilder<?> builder,

public static NetworkInterfaceStatus buildModemStatus(String interfaceId,
DevicePropertiesWrapper devicePropertiesWrapper, Optional<Properties> ip4configProperties,
List<SimProperties> simProperties, List<Properties> bearerProperties) {
Optional<Properties> ip6configProperties, List<SimProperties> simProperties,
List<Properties> bearerProperties) {
ModemInterfaceStatusBuilder builder = ModemInterfaceStatus.builder();
Properties deviceProperties = devicePropertiesWrapper.getDeviceProperties();
Optional<Properties> modemProperties = devicePropertiesWrapper.getDeviceSpecificProperties();
Expand All @@ -184,6 +193,7 @@ public static NetworkInterfaceStatus buildModemStatus(String interfaceId,

setDeviceStatus(builder, devicePropertiesWrapper);
setIP4Status(builder, ip4configProperties);
setIP6Status(builder, ip6configProperties);
setModemStatus(builder, modemProperties, simProperties, bearerProperties);

String driver = deviceProperties.Get(NM_DEVICE_BUS_NAME, "Driver");
Expand Down Expand Up @@ -245,16 +255,32 @@ private static void setIP4Status(NetworkInterfaceStatusBuilder<?> builder,
try {
NetworkInterfaceIpAddressStatus.Builder<IP4Address> ip4AddressStatusBuilder = NetworkInterfaceIpAddressStatus
.builder();
setIP4Gateway(properties, ip4AddressStatusBuilder);
setIPGateway(properties, ip4AddressStatusBuilder, IP4Address.class);
setIP4DnsServers(properties, ip4AddressStatusBuilder);
setIP4Addresses(properties, ip4AddressStatusBuilder);
setIPAddresses(properties, ip4AddressStatusBuilder, IP4Address.class);
builder.withInterfaceIp4Addresses(Optional.of(ip4AddressStatusBuilder.build()));
} catch (UnknownHostException e) {
logger.error("Failed to set IP4 address.", e);
}
});
}

private static void setIP6Status(NetworkInterfaceStatusBuilder<?> builder,
Optional<Properties> ip6configProperties) {
ip6configProperties.ifPresent(properties -> {
try {
NetworkInterfaceIpAddressStatus.Builder<IP6Address> ip6AddressStatusBuilder = NetworkInterfaceIpAddressStatus
.builder();
setIPGateway(properties, ip6AddressStatusBuilder, IP6Address.class);
setIP6DnsServers(properties, ip6AddressStatusBuilder);
setIPAddresses(properties, ip6AddressStatusBuilder, IP6Address.class);
builder.withInterfaceIp6Addresses(Optional.of(ip6AddressStatusBuilder.build()));
} catch (UnknownHostException e) {
logger.error("Failed to set IP6 address.", e);
}
});
}

private static void setWifiStatus(WifiInterfaceStatusBuilder builder, Optional<Properties> wirelessDeviceProperties,
Optional<Properties> activeAccessPoint, List<Properties> accessPoints, String countryCode,
List<WifiChannel> supportedChannels) {
Expand Down Expand Up @@ -473,18 +499,37 @@ private static WifiCapability wifiCapabilitiesConvert(NMDeviceWifiCapabilities n
}
}

private static void setIP4Addresses(Properties ip4configProperties,
NetworkInterfaceIpAddressStatus.Builder<IP4Address> builder) throws UnknownHostException {
List<Map<String, Variant<?>>> addressData = ip4configProperties.Get(NM_IP4CONFIG_BUS_NAME, "AddressData");
final List<NetworkInterfaceIpAddress<IP4Address>> addresses = new ArrayList<>();
private static <T extends IPAddress> void setIPGateway(Properties ipConfigProperties,
NetworkInterfaceIpAddressStatus.Builder<T> ipAddressStatus, Class<T> ipVersionType)
throws UnknownHostException {
String gateway = ipVersionType == IP4Address.class ? ipConfigProperties.Get(NM_IP4CONFIG_BUS_NAME, "Gateway")
: ipConfigProperties.Get(NM_IP6CONFIG_BUS_NAME, "Gateway");

if (Objects.isNull(gateway) || gateway.isEmpty()) {
return;
}

final T address = ipVersionType.cast(IPAddress.parseHostAddress(gateway));
ipAddressStatus.withGateway(Optional.of(address));
}

private static <T extends IPAddress> void setIPAddresses(Properties ipConfigProperties,
NetworkInterfaceIpAddressStatus.Builder<T> ipAddressStatus, Class<T> ipVersionType)
throws UnknownHostException {

List<Map<String, Variant<?>>> addressData = ipVersionType == IP4Address.class
? ipConfigProperties.Get(NM_IP4CONFIG_BUS_NAME, "AddressData")
: ipConfigProperties.Get(NM_IP6CONFIG_BUS_NAME, "AddressData");

final List<NetworkInterfaceIpAddress<T>> addresses = new ArrayList<>();
for (Map<String, Variant<?>> data : addressData) {
String addressStr = String.class.cast(data.get("address").getValue());
UInt32 prefix = UInt32.class.cast(data.get("prefix").getValue());
NetworkInterfaceIpAddress<IP4Address> address = new NetworkInterfaceIpAddress<>(
(IP4Address) IPAddress.parseHostAddress(addressStr), prefix.shortValue());
NetworkInterfaceIpAddress<T> address = new NetworkInterfaceIpAddress<>(
ipVersionType.cast(IPAddress.parseHostAddress(addressStr)), prefix.shortValue());
addresses.add(address);
}
builder.withAddresses(addresses);
ipAddressStatus.withAddresses(addresses);
}

private static void setIP4DnsServers(Properties ip4configProperties,
Expand All @@ -497,13 +542,21 @@ private static void setIP4DnsServers(Properties ip4configProperties,
builder.withDnsServerAddresses(dnsAddresses);
}

private static void setIP4Gateway(Properties ip4configProperties,
NetworkInterfaceIpAddressStatus.Builder<IP4Address> ip4AddressStatus) throws UnknownHostException {
String gateway = ip4configProperties.Get(NM_IP4CONFIG_BUS_NAME, "Gateway");
if (Objects.nonNull(gateway) && !gateway.isEmpty()) {
final IP4Address address = (IP4Address) IPAddress.parseHostAddress(gateway);
ip4AddressStatus.withGateway(Optional.of(address));
private static void setIP6DnsServers(Properties ip6configProperties,
NetworkInterfaceIpAddressStatus.Builder<IP6Address> builder) throws UnknownHostException {
List<List<Byte>> nameservers = ip6configProperties.Get(NM_IP6CONFIG_BUS_NAME, "Nameservers");

List<IP6Address> dnsAddresses = new ArrayList<>();
for (List<Byte> nameserver : nameservers) {
// Convert List<Byte> to byte[]
byte[] dnsByteArray = new byte[nameserver.size()];
for (int i = 0; i < nameserver.size(); i++) {
dnsByteArray[i] = nameserver.get(i);
}

dnsAddresses.add((IP6Address) IPAddress.getByAddress(dnsByteArray));
}
builder.withDnsServerAddresses(dnsAddresses);
}

private static void setModemStatus(ModemInterfaceStatusBuilder builder, Optional<Properties> modemProperties,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1167,10 +1167,8 @@ private void givenExtraStatusMocksFor(String interfaceName, NMDeviceState state,
when(mockedProperties.Get("org.freedesktop.NetworkManager.Device", "HwAddress"))
.thenReturn("F5:5B:32:7C:40:EA");

DBusPath path = mock(DBusPath.class);
when(path.getPath()).thenReturn("/");

when(mockedProperties.Get("org.freedesktop.NetworkManager.Device", "Ip4Config")).thenReturn(path);
when(mockedProperties.Get("org.freedesktop.NetworkManager.Device", "Ip4Config")).thenReturn(new DBusPath("/"));
when(mockedProperties.Get("org.freedesktop.NetworkManager.Device", "Ip6Config")).thenReturn(new DBusPath("/"));
}

private void givenModemMocksFor(String deviceId, String interfaceName, Properties mockedProperties, boolean hasBearers,
Expand Down
Loading

0 comments on commit 0a9ceb6

Please sign in to comment.