mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-07-23 11:14:29 +00:00
platform: link features (carrier-detect and vlans)
Thanks to Jiří Pírko for help with ethtool features.
This commit is contained in:
parent
3071cc6511
commit
b636ea86b1
|
@ -268,6 +268,38 @@ link_uses_arp (NMPlatform *platform, int ifindex)
|
|||
return device ? device->arp : FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
link_supports_carrier_detect (NMPlatform *platform, int ifindex)
|
||||
{
|
||||
NMPlatformLink *device = link_get (platform, ifindex);
|
||||
|
||||
if (!device)
|
||||
return FALSE;
|
||||
|
||||
switch (device->type) {
|
||||
case NM_LINK_TYPE_DUMMY:
|
||||
return FALSE;
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
link_supports_vlans (NMPlatform *platform, int ifindex)
|
||||
{
|
||||
NMPlatformLink *device = link_get (platform, ifindex);
|
||||
|
||||
if (!device)
|
||||
return FALSE;
|
||||
|
||||
switch (device->type) {
|
||||
case NM_LINK_TYPE_LOOPBACK:
|
||||
return FALSE;
|
||||
default:
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static GArray *
|
||||
|
@ -698,6 +730,9 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
|
|||
platform_class->link_is_connected = link_is_connected;
|
||||
platform_class->link_uses_arp = link_uses_arp;
|
||||
|
||||
platform_class->link_supports_carrier_detect = link_supports_carrier_detect;
|
||||
platform_class->link_supports_vlans = link_supports_vlans;
|
||||
|
||||
platform_class->ip4_address_get_all = ip4_address_get_all;
|
||||
platform_class->ip6_address_get_all = ip6_address_get_all;
|
||||
platform_class->ip4_address_add = ip4_address_add;
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#include <netinet/icmp6.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/object.h>
|
||||
#include <netlink/cache.h>
|
||||
|
@ -816,6 +819,66 @@ link_set_noarp (NMPlatform *platform, int ifindex)
|
|||
return link_change_flags (platform, ifindex, IFF_NOARP, TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ethtool_get (const char *name, gpointer edata)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int fd;
|
||||
|
||||
memset (&ifr, 0, sizeof (ifr));
|
||||
strncpy (ifr.ifr_name, name, IFNAMSIZ);
|
||||
ifr.ifr_data = edata;
|
||||
|
||||
fd = socket (PF_INET, SOCK_DGRAM, 0);
|
||||
if (fd < 0) {
|
||||
error ("ethtool: Could not open socket.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ioctl (fd, SIOCETHTOOL, &ifr) < 0) {
|
||||
debug ("ethtool: Request failed: %s", strerror (errno));
|
||||
close (fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
close (fd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
link_supports_carrier_detect (NMPlatform *platform, int ifindex)
|
||||
{
|
||||
const char *name = nm_platform_link_get_name (ifindex);
|
||||
struct ethtool_cmd edata = { .cmd = ETHTOOL_GLINK };
|
||||
|
||||
/* We ignore the result and only return FALSE on error */
|
||||
return name && ethtool_get (name, &edata);
|
||||
}
|
||||
|
||||
#define NETIF_F_VLAN_CHALLENGED (1 << 10)
|
||||
|
||||
static gboolean
|
||||
link_supports_vlans (NMPlatform *platform, int ifindex)
|
||||
{
|
||||
auto_nl_object struct rtnl_link *rtnllink = link_get (platform, ifindex);
|
||||
const char *name = nm_platform_link_get_name (ifindex);
|
||||
struct {
|
||||
struct ethtool_gfeatures features;
|
||||
struct ethtool_get_features_block features_block;
|
||||
} edata = { .features = { .cmd = ETHTOOL_GFEATURES, .size = 1 } };
|
||||
|
||||
/* Only ARPHDR_ETHER links can possibly support VLANs. Thanks to Dan Winship
|
||||
* for pointing this out.
|
||||
*/
|
||||
if (!rtnllink || rtnl_link_get_arptype (rtnllink) != ARPHRD_ETHER)
|
||||
return FALSE;
|
||||
|
||||
if (!name || !ethtool_get (name, &edata))
|
||||
return FALSE;
|
||||
|
||||
return !(edata.features.features[0].active & NETIF_F_VLAN_CHALLENGED);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
||||
static int
|
||||
|
@ -1274,6 +1337,9 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
|
|||
platform_class->link_is_connected = link_is_connected;
|
||||
platform_class->link_uses_arp = link_uses_arp;
|
||||
|
||||
platform_class->link_supports_carrier_detect = link_supports_carrier_detect;
|
||||
platform_class->link_supports_vlans = link_supports_vlans;
|
||||
|
||||
platform_class->ip4_address_get_all = ip4_address_get_all;
|
||||
platform_class->ip6_address_get_all = ip6_address_get_all;
|
||||
platform_class->ip4_address_add = ip4_address_add;
|
||||
|
|
|
@ -412,6 +412,24 @@ nm_platform_link_uses_arp (int ifindex)
|
|||
return klass->link_uses_arp (platform, ifindex);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_platform_link_supports_carrier_detect (int ifindex)
|
||||
{
|
||||
g_return_val_if_fail (ifindex >= 0, FALSE);
|
||||
g_return_val_if_fail (klass->link_supports_carrier_detect, FALSE);
|
||||
|
||||
return klass->link_supports_carrier_detect (platform, ifindex);
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_platform_link_supports_vlans (int ifindex)
|
||||
{
|
||||
g_return_val_if_fail (ifindex >= 0, FALSE);
|
||||
g_return_val_if_fail (klass->link_supports_vlans, FALSE);
|
||||
|
||||
return klass->link_supports_vlans (platform, ifindex);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_platform_link_set_up:
|
||||
* @ifindex: Interface index
|
||||
|
|
|
@ -136,6 +136,9 @@ typedef struct {
|
|||
gboolean (*link_is_connected) (NMPlatform *, int ifindex);
|
||||
gboolean (*link_uses_arp) (NMPlatform *, int ifindex);
|
||||
|
||||
gboolean (*link_supports_carrier_detect) (NMPlatform *, int ifindex);
|
||||
gboolean (*link_supports_vlans) (NMPlatform *, int ifindex);
|
||||
|
||||
GArray * (*ip4_address_get_all) (NMPlatform *, int ifindex);
|
||||
GArray * (*ip6_address_get_all) (NMPlatform *, int ifindex);
|
||||
gboolean (*ip4_address_add) (NMPlatform *, int ifindex, in_addr_t address, int plen);
|
||||
|
@ -228,6 +231,9 @@ gboolean nm_platform_link_is_up (int ifindex);
|
|||
gboolean nm_platform_link_is_connected (int ifindex);
|
||||
gboolean nm_platform_link_uses_arp (int ifindex);
|
||||
|
||||
gboolean nm_platform_link_supports_carrier_detect (int ifindex);
|
||||
gboolean nm_platform_link_supports_vlans (int ifindex);
|
||||
|
||||
GArray *nm_platform_ip4_address_get_all (int ifindex);
|
||||
GArray *nm_platform_ip6_address_get_all (int ifindex);
|
||||
gboolean nm_platform_ip4_address_add (int ifindex, in_addr_t address, int plen);
|
||||
|
|
|
@ -48,6 +48,11 @@ dump_interface (NMPlatformLink *link)
|
|||
printf (" noarp");
|
||||
printf ("\n");
|
||||
|
||||
if (nm_platform_link_supports_carrier_detect (link->ifindex))
|
||||
printf (" feature carrier-detect\n");
|
||||
if (nm_platform_link_supports_vlans (link->ifindex))
|
||||
printf (" feature vlans\n");
|
||||
|
||||
ip4_addresses = nm_platform_ip4_address_get_all (link->ifindex);
|
||||
ip6_addresses = nm_platform_ip6_address_get_all (link->ifindex);
|
||||
|
||||
|
|
|
@ -78,6 +78,11 @@ test_bogus(void)
|
|||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_uses_arp (BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
|
||||
g_assert (!nm_platform_link_supports_carrier_detect (BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
g_assert (!nm_platform_link_supports_vlans (BOGUS_IFINDEX));
|
||||
error (NM_PLATFORM_ERROR_NOT_FOUND);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -87,6 +92,9 @@ test_loopback (void)
|
|||
g_assert (nm_platform_link_get_type (LO_INDEX) == NM_LINK_TYPE_LOOPBACK);
|
||||
g_assert (nm_platform_link_get_ifindex (LO_NAME) == LO_INDEX);
|
||||
g_assert (!g_strcmp0 (nm_platform_link_get_name (LO_INDEX), LO_NAME));
|
||||
|
||||
g_assert (nm_platform_link_supports_carrier_detect (LO_INDEX));
|
||||
g_assert (!nm_platform_link_supports_vlans (LO_INDEX));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -138,6 +146,10 @@ test_internal (void)
|
|||
g_assert (!nm_platform_link_uses_arp (ifindex));
|
||||
accept_signal (link_changed);
|
||||
|
||||
/* Features */
|
||||
g_assert (!nm_platform_link_supports_carrier_detect (ifindex));
|
||||
g_assert (nm_platform_link_supports_vlans (ifindex));
|
||||
|
||||
/* Delete device */
|
||||
g_assert (nm_platform_link_delete (ifindex));
|
||||
no_error ();
|
||||
|
|
Loading…
Reference in a new issue