platform: link state, carrier and arp

This commit is contained in:
Pavel Šimerda
2013-03-27 22:23:24 +01:00
parent 15fd7cd75e
commit c1e53dbf7c
6 changed files with 432 additions and 0 deletions

View File

@@ -57,6 +57,13 @@ link_init (NMPlatformLink *device, int ifindex, int type, const char *name)
device->type = type; device->type = type;
if (name) if (name)
strcpy (device->name, name); strcpy (device->name, name);
switch (device->type) {
case NM_LINK_TYPE_DUMMY:
device->arp = FALSE;
break;
default:
device->arp = TRUE;
}
} }
static NMPlatformLink * static NMPlatformLink *
@@ -157,6 +164,106 @@ link_get_type (NMPlatform *platform, int ifindex)
return device ? device->type : NM_LINK_TYPE_NONE; return device ? device->type : NM_LINK_TYPE_NONE;
} }
static void
link_changed (NMPlatform *platform, NMPlatformLink *device)
{
g_signal_emit_by_name (platform, "link-changed", device);
}
static gboolean
link_set_up (NMPlatform *platform, int ifindex)
{
NMPlatformLink *device = link_get (platform, ifindex);
if (!device)
return FALSE;
device->up = TRUE;
switch (device->type) {
case NM_LINK_TYPE_GENERIC:
case NM_LINK_TYPE_DUMMY:
device->connected = TRUE;
break;
default:
device->connected = FALSE;
g_error ("Unexpected device type: %d", device->type);
}
link_changed (platform, device);
return TRUE;
}
static gboolean
link_set_down (NMPlatform *platform, int ifindex)
{
NMPlatformLink *device = link_get (platform, ifindex);
if (!device)
return FALSE;
device->up = FALSE;
device->connected = FALSE;
link_changed (platform, device);
return TRUE;
}
static gboolean
link_set_arp (NMPlatform *platform, int ifindex)
{
NMPlatformLink *device = link_get (platform, ifindex);
if (!device)
return FALSE;
device->arp = TRUE;
link_changed (platform, device);
return TRUE;
}
static gboolean
link_set_noarp (NMPlatform *platform, int ifindex)
{
NMPlatformLink *device = link_get (platform, ifindex);
if (!device)
return FALSE;
device->arp = FALSE;
link_changed (platform, device);
return TRUE;
}
static gboolean
link_is_up (NMPlatform *platform, int ifindex)
{
NMPlatformLink *device = link_get (platform, ifindex);
return device ? device->up : FALSE;
}
static gboolean
link_is_connected (NMPlatform *platform, int ifindex)
{
NMPlatformLink *device = link_get (platform, ifindex);
return device ? device->connected : FALSE;
}
static gboolean
link_uses_arp (NMPlatform *platform, int ifindex)
{
NMPlatformLink *device = link_get (platform, ifindex);
return device ? device->arp : FALSE;
}
/******************************************************************/ /******************************************************************/
static void static void
@@ -213,4 +320,12 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
platform_class->link_get_ifindex = link_get_ifindex; platform_class->link_get_ifindex = link_get_ifindex;
platform_class->link_get_name = link_get_name; platform_class->link_get_name = link_get_name;
platform_class->link_get_type = link_get_type; platform_class->link_get_type = link_get_type;
platform_class->link_set_up = link_set_up;
platform_class->link_set_down = link_set_down;
platform_class->link_set_arp = link_set_arp;
platform_class->link_set_noarp = link_set_noarp;
platform_class->link_is_up = link_is_up;
platform_class->link_is_connected = link_is_connected;
platform_class->link_uses_arp = link_uses_arp;
} }

View File

@@ -240,6 +240,9 @@ link_init (NMPlatformLink *info, struct rtnl_link *rtnllink)
info->ifindex = rtnl_link_get_ifindex (rtnllink); info->ifindex = rtnl_link_get_ifindex (rtnllink);
strcpy (info->name, rtnl_link_get_name (rtnllink)); strcpy (info->name, rtnl_link_get_name (rtnllink));
info->type = link_extract_type (rtnllink); info->type = link_extract_type (rtnllink);
info->up = !!(rtnl_link_get_flags (rtnllink) & IFF_UP);
info->connected = !!(rtnl_link_get_flags (rtnllink) & IFF_LOWER_UP);
info->arp = !(rtnl_link_get_flags (rtnllink) & IFF_NOARP);
} }
/******************************************************************/ /******************************************************************/
@@ -502,6 +505,24 @@ link_add (NMPlatform *platform, const char *name, NMLinkType type)
return add_object (platform, build_rtnl_link (0, name, type)); return add_object (platform, build_rtnl_link (0, name, type));
} }
static gboolean
link_change (NMPlatform *platform, int ifindex, struct rtnl_link *change)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
auto_nl_object struct rtnl_link *orig;
orig = rtnl_link_get (priv->link_cache, ifindex);
if (!orig) {
debug ("link not found: %d", ifindex);
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
return FALSE;
}
return refresh_object (platform, (struct nl_object *) orig,
rtnl_link_change (priv->nlh, orig, change, 0));
}
static gboolean static gboolean
link_delete (NMPlatform *platform, int ifindex) link_delete (NMPlatform *platform, int ifindex)
{ {
@@ -544,6 +565,81 @@ link_get_type (NMPlatform *platform, int ifindex)
return link_extract_type (rtnllink); return link_extract_type (rtnllink);
} }
static guint32
link_get_flags (NMPlatform *platform, int ifindex)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
auto_nl_object struct rtnl_link *rtnllink;
rtnllink = rtnl_link_get (priv->link_cache, ifindex);
if (!rtnllink) {
debug ("link not found: %d", ifindex);
platform->error = NM_PLATFORM_ERROR_NOT_FOUND;
return IFF_NOARP;
}
return rtnl_link_get_flags (rtnllink);
}
static gboolean
link_is_up (NMPlatform *platform, int ifindex)
{
return !!(link_get_flags (platform, ifindex) & IFF_UP);
}
static gboolean
link_is_connected (NMPlatform *platform, int ifindex)
{
return !!(link_get_flags (platform, ifindex) & IFF_LOWER_UP);
}
static gboolean
link_uses_arp (NMPlatform *platform, int ifindex)
{
return !(link_get_flags (platform, ifindex) & IFF_NOARP);
}
static gboolean
link_change_flags (NMPlatform *platform, int ifindex, unsigned int flags, gboolean value)
{
auto_nl_object struct rtnl_link *change;
change = rtnl_link_alloc ();
g_return_val_if_fail (change != NULL, FALSE);
if (value)
rtnl_link_set_flags (change, flags);
else
rtnl_link_unset_flags (change, flags);
return link_change (platform, ifindex, change);
}
static gboolean
link_set_up (NMPlatform *platform, int ifindex)
{
return link_change_flags (platform, ifindex, IFF_UP, TRUE);
}
static gboolean
link_set_down (NMPlatform *platform, int ifindex)
{
return link_change_flags (platform, ifindex, IFF_UP, FALSE);
}
static gboolean
link_set_arp (NMPlatform *platform, int ifindex)
{
return link_change_flags (platform, ifindex, IFF_NOARP, FALSE);
}
static gboolean
link_set_noarp (NMPlatform *platform, int ifindex)
{
return link_change_flags (platform, ifindex, IFF_NOARP, TRUE);
}
/******************************************************************/ /******************************************************************/
#define EVENT_CONDITIONS ((GIOCondition) (G_IO_IN | G_IO_PRI)) #define EVENT_CONDITIONS ((GIOCondition) (G_IO_IN | G_IO_PRI))
@@ -698,4 +794,12 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->link_get_ifindex = link_get_ifindex; platform_class->link_get_ifindex = link_get_ifindex;
platform_class->link_get_name = link_get_name; platform_class->link_get_name = link_get_name;
platform_class->link_get_type = link_get_type; platform_class->link_get_type = link_get_type;
platform_class->link_set_up = link_set_up;
platform_class->link_set_down = link_set_down;
platform_class->link_set_arp = link_set_arp;
platform_class->link_set_noarp = link_set_noarp;
platform_class->link_is_up = link_is_up;
platform_class->link_is_connected = link_is_connected;
platform_class->link_uses_arp = link_uses_arp;
} }

View File

@@ -348,6 +348,129 @@ nm_platform_link_get_type (int ifindex)
return klass->link_get_type (platform, ifindex); return klass->link_get_type (platform, ifindex);
} }
/**
* nm_platform_link_is_up:
* @ifindex: Interface index
*
* Check if the interface is up.
*/
gboolean
nm_platform_link_is_up (int ifindex)
{
reset_error ();
g_return_val_if_fail (ifindex >= 0, FALSE);
g_return_val_if_fail (klass->link_is_up, FALSE);
return klass->link_is_up (platform, ifindex);
}
/**
* nm_platform_link_is_connected:
* @ifindex: Interface index
*
* Check if the interface is connected.
*/
gboolean
nm_platform_link_is_connected (int ifindex)
{
reset_error ();
g_return_val_if_fail (ifindex >= 0, FALSE);
g_return_val_if_fail (klass->link_is_connected, FALSE);
return klass->link_is_connected (platform, ifindex);
}
/**
* nm_platform_link_uses_arp:
* @ifindex: Interface index
*
* Check if the interface is configured to use ARP.
*/
gboolean
nm_platform_link_uses_arp (int ifindex)
{
reset_error ();
g_return_val_if_fail (ifindex >= 0, FALSE);
g_return_val_if_fail (klass->link_uses_arp, FALSE);
return klass->link_uses_arp (platform, ifindex);
}
/**
* nm_platform_link_set_up:
* @ifindex: Interface index
*
* Bring the interface up.
*/
gboolean
nm_platform_link_set_up (int ifindex)
{
reset_error ();
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (klass->link_set_up, FALSE);
debug ("link: setting up '%s' (%d)", nm_platform_link_get_name (ifindex), ifindex);
return klass->link_set_up (platform, ifindex);
}
/**
* nm_platform_link_set_down:
* @ifindex: Interface index
*
* Take the interface down.
*/
gboolean
nm_platform_link_set_down (int ifindex)
{
reset_error ();
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (klass->link_set_down, FALSE);
debug ("link: setting down '%s' (%d)", nm_platform_link_get_name (ifindex), ifindex);
return klass->link_set_down (platform, ifindex);
}
/**
* nm_platform_link_set_arp:
* @ifindex: Interface index
*
* Enable ARP on the interface.
*/
gboolean
nm_platform_link_set_arp (int ifindex)
{
reset_error ();
g_return_val_if_fail (ifindex >= 0, FALSE);
g_return_val_if_fail (klass->link_set_arp, FALSE);
debug ("link: setting arp '%s' (%d)", nm_platform_link_get_name (ifindex), ifindex);
return klass->link_set_arp (platform, ifindex);
}
/**
* nm_platform_link_set_noarp:
* @ifindex: Interface index
*
* Disable ARP on the interface.
*/
gboolean
nm_platform_link_set_noarp (int ifindex)
{
reset_error ();
g_return_val_if_fail (ifindex >= 0, FALSE);
g_return_val_if_fail (klass->link_set_noarp, FALSE);
debug ("link: setting noarp '%s' (%d)", nm_platform_link_get_name (ifindex), ifindex);
return klass->link_set_noarp (platform, ifindex);
}
/******************************************************************/ /******************************************************************/
static void static void

View File

@@ -47,6 +47,9 @@ typedef struct {
int ifindex; int ifindex;
char name[IFNAMSIZ]; char name[IFNAMSIZ];
NMLinkType type; NMLinkType type;
gboolean up;
gboolean connected;
gboolean arp;
} NMPlatformLink; } NMPlatformLink;
/******************************************************************/ /******************************************************************/
@@ -96,6 +99,14 @@ typedef struct {
int (*link_get_ifindex) (NMPlatform *, const char *name); int (*link_get_ifindex) (NMPlatform *, const char *name);
const char *(*link_get_name) (NMPlatform *, int ifindex); const char *(*link_get_name) (NMPlatform *, int ifindex);
NMLinkType (*link_get_type) (NMPlatform *, int ifindex); NMLinkType (*link_get_type) (NMPlatform *, int ifindex);
gboolean (*link_set_up) (NMPlatform *, int ifindex);
gboolean (*link_set_down) (NMPlatform *, int ifindex);
gboolean (*link_set_arp) (NMPlatform *, int ifindex);
gboolean (*link_set_noarp) (NMPlatform *, int ifindex);
gboolean (*link_is_up) (NMPlatform *, int ifindex);
gboolean (*link_is_connected) (NMPlatform *, int ifindex);
gboolean (*link_uses_arp) (NMPlatform *, int ifindex);
} NMPlatformClass; } NMPlatformClass;
/* NMPlatform signals /* NMPlatform signals
@@ -145,4 +156,12 @@ int nm_platform_link_get_ifindex (const char *name);
const char *nm_platform_link_get_name (int ifindex); const char *nm_platform_link_get_name (int ifindex);
NMLinkType nm_platform_link_get_type (int ifindex); NMLinkType nm_platform_link_get_type (int ifindex);
gboolean nm_platform_link_set_up (int ifindex);
gboolean nm_platform_link_set_down (int ifindex);
gboolean nm_platform_link_set_arp (int ifindex);
gboolean nm_platform_link_set_noarp (int ifindex);
gboolean nm_platform_link_is_up (int ifindex);
gboolean nm_platform_link_is_connected (int ifindex);
gboolean nm_platform_link_uses_arp (int ifindex);
#endif /* NM_PLATFORM_H */ #endif /* NM_PLATFORM_H */

View File

@@ -23,7 +23,15 @@ type_to_string (NMLinkType type)
static void static void
dump_interface (NMPlatformLink *link) dump_interface (NMPlatformLink *link)
{ {
g_assert (link->up || !link->connected);
printf ("%d: %s: %s", link->ifindex, link->name, type_to_string (link->type)); printf ("%d: %s: %s", link->ifindex, link->name, type_to_string (link->type));
if (link->up)
printf (" %s", link->connected ? "CONNECTED" : "DISCONNECTED");
else
printf (" DOWN");
if (!link->arp)
printf (" noarp");
printf ("\n"); printf ("\n");
} }

View File

@@ -63,6 +63,21 @@ test_bogus(void)
error (NM_PLATFORM_ERROR_NOT_FOUND); error (NM_PLATFORM_ERROR_NOT_FOUND);
g_assert (!nm_platform_link_get_type (BOGUS_IFINDEX)); g_assert (!nm_platform_link_get_type (BOGUS_IFINDEX));
error (NM_PLATFORM_ERROR_NOT_FOUND); error (NM_PLATFORM_ERROR_NOT_FOUND);
g_assert (!nm_platform_link_set_up (BOGUS_IFINDEX));
error (NM_PLATFORM_ERROR_NOT_FOUND);
g_assert (!nm_platform_link_set_down (BOGUS_IFINDEX));
error (NM_PLATFORM_ERROR_NOT_FOUND);
g_assert (!nm_platform_link_set_arp (BOGUS_IFINDEX));
error (NM_PLATFORM_ERROR_NOT_FOUND);
g_assert (!nm_platform_link_set_noarp (BOGUS_IFINDEX));
error (NM_PLATFORM_ERROR_NOT_FOUND);
g_assert (!nm_platform_link_is_up (BOGUS_IFINDEX));
error (NM_PLATFORM_ERROR_NOT_FOUND);
g_assert (!nm_platform_link_is_connected (BOGUS_IFINDEX));
error (NM_PLATFORM_ERROR_NOT_FOUND);
g_assert (!nm_platform_link_uses_arp (BOGUS_IFINDEX));
error (NM_PLATFORM_ERROR_NOT_FOUND);
} }
static void static void
@@ -102,6 +117,27 @@ test_internal (void)
g_assert (!g_strcmp0 (nm_platform_link_get_name (ifindex), DEVICE_NAME)); g_assert (!g_strcmp0 (nm_platform_link_get_name (ifindex), DEVICE_NAME));
g_assert (nm_platform_link_get_type (ifindex) == NM_LINK_TYPE_DUMMY); g_assert (nm_platform_link_get_type (ifindex) == NM_LINK_TYPE_DUMMY);
/* Up/connected */
g_assert (!nm_platform_link_is_up (ifindex)); no_error ();
g_assert (!nm_platform_link_is_connected (ifindex)); no_error ();
g_assert (nm_platform_link_set_up (ifindex)); no_error ();
g_assert (nm_platform_link_is_up (ifindex)); no_error ();
g_assert (nm_platform_link_is_connected (ifindex)); no_error ();
accept_signal (link_changed);
g_assert (nm_platform_link_set_down (ifindex)); no_error ();
g_assert (!nm_platform_link_is_up (ifindex)); no_error ();
g_assert (!nm_platform_link_is_connected (ifindex)); no_error ();
accept_signal (link_changed);
/* arp/noarp */
g_assert (!nm_platform_link_uses_arp (ifindex));
g_assert (nm_platform_link_set_arp (ifindex));
g_assert (nm_platform_link_uses_arp (ifindex));
accept_signal (link_changed);
g_assert (nm_platform_link_set_noarp (ifindex));
g_assert (!nm_platform_link_uses_arp (ifindex));
accept_signal (link_changed);
/* Delete device */ /* Delete device */
g_assert (nm_platform_link_delete (ifindex)); g_assert (nm_platform_link_delete (ifindex));
no_error (); no_error ();
@@ -146,6 +182,33 @@ test_external (void)
g_assert (!g_strcmp0 (nm_platform_link_get_name (ifindex), DEVICE_NAME)); g_assert (!g_strcmp0 (nm_platform_link_get_name (ifindex), DEVICE_NAME));
g_assert (nm_platform_link_get_type (ifindex) == NM_LINK_TYPE_DUMMY); g_assert (nm_platform_link_get_type (ifindex) == NM_LINK_TYPE_DUMMY);
/* Up/connected/arp */
g_assert (!nm_platform_link_is_up (ifindex));
g_assert (!nm_platform_link_is_connected (ifindex));
g_assert (!nm_platform_link_uses_arp (ifindex));
run_command ("ip link set %s up", DEVICE_NAME);
wait_signal (link_changed);
g_assert (nm_platform_link_is_up (ifindex));
g_assert (nm_platform_link_is_connected (ifindex));
run_command ("ip link set %s down", DEVICE_NAME);
wait_signal (link_changed);
g_assert (!nm_platform_link_is_up (ifindex));
g_assert (!nm_platform_link_is_connected (ifindex));
/* This test doesn't trigger a netlink event at least on
* 3.8.2-206.fc18.x86_64. Disabling the waiting and checking code
* because of that.
*/
run_command ("ip link set %s arp on", DEVICE_NAME);
#if 0
wait_signal (link_changed);
g_assert (nm_platform_link_uses_arp (ifindex));
#endif
run_command ("ip link set %s arp off", DEVICE_NAME);
#if 0
wait_signal (link_changed);
g_assert (!nm_platform_link_uses_arp (ifindex));
#endif
run_command ("ip link del %s", DEVICE_NAME); run_command ("ip link del %s", DEVICE_NAME);
wait_signal (link_removed); wait_signal (link_removed);
g_assert (!nm_platform_link_exists (DEVICE_NAME)); g_assert (!nm_platform_link_exists (DEVICE_NAME));