[NetworkManager/f20] Add physical-port-id property for devices and fix GI for IPv6

Jirka Klimes jklimes at fedoraproject.org
Tue Jan 21 11:14:29 UTC 2014


commit d112c5a56cd4dc2e62b06db3459ca26f4dd9a270
Author: Jiří Klimeš <jklimes at redhat.com>
Date:   Tue Jan 21 11:42:28 2014 +0100

    Add physical-port-id property for devices and fix GI for IPv6
    
    - core: improve handling of NPAR/SR-IOV devices (rh #804527)
    - libnm-glib: add NMDevice:physical-port-id property
    - libnm-glib: fix introspection annotations so that <ipv6>.get_address() worked

 NetworkManager.spec    |   11 +-
 gi-fix-for-ipv6.patch  |  230 +++++++++++++++++++++
 physical-port-id.patch |  520 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 760 insertions(+), 1 deletions(-)
---
diff --git a/NetworkManager.spec b/NetworkManager.spec
index 1a49c57..1e47cad 100644
--- a/NetworkManager.spec
+++ b/NetworkManager.spec
@@ -19,7 +19,7 @@ Name: NetworkManager
 Summary: Network connection manager and user applications
 Epoch: 1
 Version: 0.9.9.0
-Release: 25%{snapshot}%{?dist}
+Release: 26%{snapshot}%{?dist}
 Group: System Environment/Base
 License: GPLv2+
 URL: http://www.gnome.org/projects/NetworkManager/
@@ -54,6 +54,8 @@ Patch24: vpn-connection-states.patch
 Patch25: nmcli-group-dot-field.patch
 Patch26: rh1036132-VPN-active-con-info.patch
 Patch27: rh1031574-primary-connection.patch
+Patch28: physical-port-id.patch
+Patch29: gi-fix-for-ipv6.patch
 
 BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
@@ -204,6 +206,8 @@ deployments.
 %patch25 -p1 -b .nmcli-group-dot-field
 %patch26 -p1 -b .VPN-active-con-info
 %patch27 -p1 -b .primary-connection
+%patch28 -p1 -b .physical-port-id
+%patch29 -p1 -b .gi-fix-for-ipv6
 
 %build
 
@@ -402,6 +406,11 @@ fi
 %config %{_sysconfdir}/%{name}/conf.d/00-server.conf
 
 %changelog
+* Tue Jan 21 2014 Jiří Klimeš <jklimes at redhat.com> - 0.9.9.0-26.git20131003
+- core: improve handling of NPAR/SR-IOV devices (rh #804527)
+- libnm-glib: add NMDevice:physical-port-id property
+- libnm-glib: fix introspection annotations so that <ipv6>.get_address() worked
+
 * Sat Jan 18 2014 Dan Winship <danw at redhat.com> - 0.9.9.0-25.git20131003
 - core: fix NMManager:primary-connection when a VPN has the default route (rh #1031574)
 
diff --git a/gi-fix-for-ipv6.patch b/gi-fix-for-ipv6.patch
new file mode 100644
index 0000000..c633d9a
--- /dev/null
+++ b/gi-fix-for-ipv6.patch
@@ -0,0 +1,230 @@
+From 7ffbbae3a046dbb4c8d5089c41b143eafabed709 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= <jklimes at redhat.com>
+Date: Thu, 16 Jan 2014 17:29:08 +0100
+Subject: [PATCH 1/2] libnm-glib; fix introspection annotations so that
+ <ipv6>.get_address() worked
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Without the correct annotation, the functions didn't work correctly in Python
+(causing segmentation fault).
+
+Signed-off-by: Jiří Klimeš <jklimes at redhat.com>
+---
+ libnm-util/nm-setting-ip6-config.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/libnm-util/nm-setting-ip6-config.c b/libnm-util/nm-setting-ip6-config.c
+index 7798db3..b02e231 100644
+--- a/libnm-util/nm-setting-ip6-config.c
++++ b/libnm-util/nm-setting-ip6-config.c
+@@ -1285,7 +1285,8 @@ nm_ip6_address_compare (NMIP6Address *address, NMIP6Address *other)
+  *
+  * Gets the IPv6 address property of this address object.
+  *
+- * Returns: (transfer none): the IPv6 address
++ * Returns: (array fixed-size=16) (element-type guint8) (transfer none):
++ *          the IPv6 address
+  **/
+ const struct in6_addr *
+ nm_ip6_address_get_address (NMIP6Address *address)
+@@ -1354,7 +1355,9 @@ nm_ip6_address_set_prefix (NMIP6Address *address, guint32 prefix)
+  *
+  * Gets the IPv6 default gateway property of this address object.
+  *
+- * Returns: (transfer none): the IPv6 gateway address
++ * Returns: (transfer none): 
++ * Returns: (array fixed-size=16) (element-type guint8) (transfer none):
++ *          the IPv6 gateway address
+  **/
+ const struct in6_addr *
+ nm_ip6_address_get_gateway (NMIP6Address *address)
+@@ -1502,7 +1505,8 @@ nm_ip6_route_compare (NMIP6Route *route, NMIP6Route *other)
+  *
+  * Gets the IPv6 destination address property of this route object.
+  *
+- * Returns: the IPv6 address
++ * Returns: (array fixed-size=16) (element-type guint8) (transfer none):
++ *          the IPv6 address of destination
+  **/
+ const struct in6_addr *
+ nm_ip6_route_get_dest (NMIP6Route *route)
+@@ -1571,7 +1575,8 @@ nm_ip6_route_set_prefix (NMIP6Route *route, guint32 prefix)
+  *
+  * Gets the IPv6 address of the next hop of this route.
+  *
+- * Returns: the IPv6 address
++ * Returns: (array fixed-size=16) (element-type guint8) (transfer none):
++ *          the IPv6 address of next hop
+  **/
+ const struct in6_addr *
+ nm_ip6_route_get_next_hop (NMIP6Route *route)
+-- 
+1.7.11.7
+
+
+From 68fe50ff3a4774c0abff1d6f8c2f270b73105351 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= <jklimes at redhat.com>
+Date: Thu, 16 Jan 2014 17:27:05 +0100
+Subject: [PATCH 2/2] examples: add an python example (using GI) getting
+ device IPs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+
+Signed-off-by: Jiří Klimeš <jklimes at redhat.com>
+---
+ examples/python/gi/Makefile.am |   3 +-
+ examples/python/gi/get_ips.py  | 127 +++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 129 insertions(+), 1 deletion(-)
+ create mode 100755 examples/python/gi/get_ips.py
+
+diff --git a/examples/python/gi/Makefile.am b/examples/python/gi/Makefile.am
+index 78569b3..7f122a4 100644
+--- a/examples/python/gi/Makefile.am
++++ b/examples/python/gi/Makefile.am
+@@ -2,4 +2,5 @@ EXTRA_DIST = \
+ 	list-connections.py \
+ 	device-state-ip4config.py \
+ 	firewall-zone.py \
+-	show-wifi-networks.py
++	show-wifi-networks.py \
++	get_ips.py
+diff --git a/examples/python/gi/get_ips.py b/examples/python/gi/get_ips.py
+new file mode 100755
+index 0000000..b1e59e2
+--- /dev/null
++++ b/examples/python/gi/get_ips.py
+@@ -0,0 +1,127 @@
++#!/usr/bin/env python
++#
++# vim: ft=python ts=4 sts=4 sw=4 et ai
++# -*- Mode: Python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License along
++# with this program; if not, write to the Free Software Foundation, Inc.,
++# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++#
++# Copyright (C) 2014 Red Hat, Inc.
++#
++
++import sys, socket, struct
++from gi.repository import GLib, NetworkManager, NMClient
++
++#
++#  This example shows how to get get addresses and routes from NMIP4Config and NMIP6Config
++#  (got out of NMDevice)
++#
++
++def show_addresses(self, family):
++    if (family == socket.AF_INET):
++       ip_cfg = self.get_ip4_config()
++    else:
++       ip_cfg = self.get_ip6_config()
++
++    if ip_cfg is None:
++        print("None")
++        return
++
++    nm_addresses = ip_cfg.get_addresses()
++    if len(nm_addresses) == 0:
++        print("None")
++        return
++
++    for nm_address in nm_addresses:
++        addr = nm_address.get_address()
++        prefix = nm_address.get_prefix()
++        gateway = nm_address.get_gateway()
++
++        if (family == socket.AF_INET):
++            addr_struct = struct.pack("=I", addr)
++            gateway_struct = struct.pack("=I", gateway)
++        else:
++            addr_struct = addr
++            gateway_struct = gateway
++        print("%s/%d  %s") % (socket.inet_ntop(family, addr_struct),
++                              prefix,
++                              socket.inet_ntop(family, gateway_struct))
++
++
++
++def show_routes(self, family):
++    if (family == socket.AF_INET):
++       ip_cfg = self.get_ip4_config()
++    else:
++       ip_cfg = self.get_ip6_config()
++
++    if ip_cfg is None:
++        print("None")
++        return
++
++    nm_routes = ip_cfg.get_routes() 
++    if len(nm_routes) == 0:
++        print("None")
++        return
++
++    for nm_route in nm_routes:
++        dest = nm_route.get_dest()
++        prefix = nm_route.get_prefix()
++        next_hop = nm_route.get_next_hop()
++        metric = nm_route.get_metric()
++
++        if (family == socket.AF_INET):
++            dest_struct = struct.pack("=I", dest)
++            next_hop_struct = struct.pack("=I", next_hop)
++        else:
++            dest_struct = dest
++            next_hop_struct = next_hop
++        print("%s/%d  %s  %d") % (socket.inet_ntop(family, dest_struct),
++                                  prefix,
++                                  socket.inet_ntop(family, next_hop_struct),
++                                  metric)
++
++
++if __name__ == "__main__":
++    if len(sys.argv) != 2:
++        sys.exit('Usage: %s <interface>' % sys.argv[0])
++    dev_iface = sys.argv[1]
++
++    c = NMClient.Client.new()
++    dev = c.get_device_by_iface(dev_iface)
++    if dev is None:
++        sys.exit('Device \'%s\' not found' % dev_iface)
++    print "Device: %s - %s" % (dev_iface, dev.get_device_type().value_name)
++    print "---------------------------------------"
++
++    print("IPv4 addresses:")
++    print("---------------")
++    show_addresses(dev, socket.AF_INET)
++    print
++
++    print("IPv4 routes:")
++    print("------------")
++    show_routes(dev, socket.AF_INET)
++    print
++
++    print "IPv6 addresses:"
++    print("---------------")
++    show_addresses(dev, socket.AF_INET6)
++    print
++
++    print "IPv6 routes:"
++    print("------------")
++    show_routes(dev, socket.AF_INET6)
++    print
++
+-- 
+1.7.11.7
+
diff --git a/physical-port-id.patch b/physical-port-id.patch
new file mode 100644
index 0000000..3ba149d
--- /dev/null
+++ b/physical-port-id.patch
@@ -0,0 +1,520 @@
+From b7300bbe5a9f298ede02225b6b7e73e05aa78bc8 Mon Sep 17 00:00:00 2001
+From: Dan Winship <danw at gnome.org>
+Date: Fri, 11 Oct 2013 14:59:26 -0400
+Subject: [PATCH 1/2] core: improve handling of NPAR/SR-IOV devices (rh
+ #804527)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Use the new kernel physical_port_id interface property to recognize
+when two devices are just virtual devices sharing the same physical
+port, and refuse to bond/team multiple slaves on the same port.
+
+Signed-off-by: Jiří Klimeš <jklimes at redhat.com>
+---
+ introspection/nm-device.xml      |  8 +++++
+ src/devices/nm-device-bond.c     |  2 ++
+ src/devices/nm-device-private.h  |  3 ++
+ src/devices/nm-device-team.c     |  2 ++
+ src/devices/nm-device.c          | 70 +++++++++++++++++++++++++++++++++++++++-
+ src/devices/nm-device.h          |  3 ++
+ src/platform/nm-fake-platform.c  | 11 +++++++
+ src/platform/nm-linux-platform.c | 22 +++++++++++++
+ src/platform/nm-platform.c       | 18 +++++++++++
+ src/platform/nm-platform.h       |  4 +++
+ 10 files changed, 142 insertions(+), 1 deletion(-)
+
+diff --git a/introspection/nm-device.xml b/introspection/nm-device.xml
+index 7c63a3d..d9e7702 100644
+--- a/introspection/nm-device.xml
++++ b/introspection/nm-device.xml
+@@ -125,6 +125,14 @@
+         An array of object paths of every configured connection that is currently 'available' through this device.
+       </tp:docstring>
+     </property>
++    <property name="PhysicalPortId" type="s" access="read">
++      <tp:docstring>
++        If non-empty, an (opaque) indicator of the physical network
++        port associated with the device. This can be used to recognize
++	when two seemingly-separate hardware devices are actually just
++	different virtual interfaces to the same physical port.
++      </tp:docstring>
++    </property>
+ 
+     <method name="Disconnect">
+       <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="impl_device_disconnect"/>
+diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c
+index 950bbb8..82e5a9d 100644
+--- a/src/devices/nm-device-bond.c
++++ b/src/devices/nm-device-bond.c
+@@ -364,6 +364,8 @@ enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
+ 	const char *iface = nm_device_get_ip_iface (device);
+ 	const char *slave_iface = nm_device_get_ip_iface (slave);
+ 
++	nm_device_master_check_slave_physical_port (device, slave, LOGD_BOND);
++
+ 	nm_device_take_down (slave, TRUE);
+ 
+ 	success = nm_platform_link_enslave (nm_device_get_ip_ifindex (device),
+diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h
+index dc72886..3da1479 100644
+--- a/src/devices/nm-device-private.h
++++ b/src/devices/nm-device-private.h
+@@ -92,6 +92,9 @@ gboolean nm_device_get_enslaved (NMDevice *device);
+ 
+ NMDevice *nm_device_master_get_slave_by_ifindex (NMDevice *dev, int ifindex);
+ 
++void nm_device_master_check_slave_physical_port (NMDevice *dev, NMDevice *slave,
++                                                 guint64 log_domain);
++
+ void nm_device_set_carrier (NMDevice *device, gboolean carrier);
+ 
+ #endif	/* NM_DEVICE_PRIVATE_H */
+diff --git a/src/devices/nm-device-team.c b/src/devices/nm-device-team.c
+index 1b3b0c0..31806bc 100644
+--- a/src/devices/nm-device-team.c
++++ b/src/devices/nm-device-team.c
+@@ -546,6 +546,8 @@ enslave_slave (NMDevice *device, NMDevice *slave, NMConnection *connection)
+ 	const char *slave_iface = nm_device_get_ip_iface (slave);
+ 	NMSettingTeamPort *s_team_port;
+ 
++	nm_device_master_check_slave_physical_port (device, slave, LOGD_TEAM);
++
+ 	nm_device_take_down (slave, TRUE);
+ 
+ 	s_team_port = nm_connection_get_setting_team_port (connection);
+diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
+index 4ef5030..a0bf465 100644
+--- a/src/devices/nm-device.c
++++ b/src/devices/nm-device.c
+@@ -129,6 +129,7 @@ enum {
+ 	PROP_RFKILL_TYPE,
+ 	PROP_IFINDEX,
+ 	PROP_AVAILABLE_CONNECTIONS,
++	PROP_PHYSICAL_PORT_ID,
+ 	PROP_IS_MASTER,
+ 	PROP_HW_ADDRESS,
+ 	PROP_HAS_PENDING_ACTION,
+@@ -202,6 +203,7 @@ typedef struct {
+ 	GHashTable *  available_connections;
+ 	guint8        hw_addr[NM_UTILS_HWADDR_LEN_MAX];
+ 	guint         hw_addr_len;
++	char *        physical_port_id;
+ 
+ 	gboolean      manager_managed; /* whether managed by NMManager or not */
+ 	gboolean      default_unmanaged; /* whether unmanaged by default */
+@@ -589,8 +591,10 @@ constructed (GObject *object)
+ 		priv->carrier = TRUE;
+ 	}
+ 
+-	if (priv->ifindex > 0)
++	if (priv->ifindex > 0) {
+ 		priv->is_software = nm_platform_link_is_software (priv->ifindex);
++		priv->physical_port_id = nm_platform_link_get_physical_port_id (priv->ifindex);
++	}
+ 
+ 	if (G_OBJECT_CLASS (nm_device_parent_class)->constructed)
+ 		G_OBJECT_CLASS (nm_device_parent_class)->constructed (object);
+@@ -1338,6 +1342,49 @@ nm_device_master_get_slave_by_ifindex (NMDevice *dev, int ifindex)
+ }
+ 
+ /**
++ * nm_device_master_check_slave_physical_port:
++ * @dev: the master device
++ * @slave: a slave device
++ * @log_domain: domain to log a warning in
++ *
++ * Checks if @dev already has a slave with the same #NMDevice:physical-port-id
++ * as @slave, and logs a warning if so.
++ */
++void
++nm_device_master_check_slave_physical_port (NMDevice *dev, NMDevice *slave,
++                                            guint64 log_domain)
++{
++	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (dev);
++	const char *slave_physical_port_id, *existing_physical_port_id;
++	SlaveInfo *info;
++	GSList *iter;
++
++	slave_physical_port_id = nm_device_get_physical_port_id (slave);
++	if (!slave_physical_port_id)
++		return;
++
++	for (iter = priv->slaves; iter; iter = iter->next) {
++		info = iter->data;
++		if (info->slave == slave)
++			continue;
++
++		existing_physical_port_id = nm_device_get_physical_port_id (info->slave);
++		if (!g_strcmp0 (slave_physical_port_id, existing_physical_port_id)) {
++			nm_log_warn (log_domain, "(%s): slave %s shares a physical port with existing slave %s",
++			             nm_device_get_ip_iface (dev),
++			             nm_device_get_ip_iface (slave),
++			             nm_device_get_ip_iface (info->slave));
++			/* Since this function will get called for every slave, we only have
++			 * to warn about the first match we find; if there are other matches
++			 * later in the list, we will have already warned about them matching
++			 * @existing earlier.
++			 */
++			return;
++		}
++	}
++}
++
++/**
+  * nm_device_is_master:
+  * @dev: the device
+  *
+@@ -5172,6 +5219,8 @@ dispose (GObject *object)
+ 	g_hash_table_unref (priv->available_connections);
+ 	priv->available_connections = NULL;
+ 
++	g_clear_pointer (&priv->physical_port_id, g_free);
++
+ 	activation_source_clear (self, TRUE, AF_INET);
+ 	activation_source_clear (self, TRUE, AF_INET6);
+ 
+@@ -5432,6 +5481,9 @@ get_property (GObject *object, guint prop_id,
+ 			g_ptr_array_add (array, g_strdup (nm_connection_get_path (connection)));
+ 		g_value_take_boxed (value, array);
+ 		break;
++	case PROP_PHYSICAL_PORT_ID:
++		g_value_set_string (value, priv->physical_port_id);
++		break;
+ 	case PROP_IS_MASTER:
+ 		g_value_set_boolean (value, priv->is_master);
+ 		break;
+@@ -5689,6 +5741,14 @@ nm_device_class_init (NMDeviceClass *klass)
+ 		                     G_PARAM_READABLE));
+ 
+ 	g_object_class_install_property
++		(object_class, PROP_PHYSICAL_PORT_ID,
++		 g_param_spec_string (NM_DEVICE_PHYSICAL_PORT_ID,
++		                      "PhysicalPortId",
++		                      "PhysicalPortId",
++		                      NULL,
++		                      G_PARAM_READABLE));
++
++	g_object_class_install_property
+ 		(object_class, PROP_IS_MASTER,
+ 		 g_param_spec_boolean (NM_DEVICE_IS_MASTER,
+ 		                       "IsMaster",
+@@ -6908,3 +6968,11 @@ nm_device_has_pending_action (NMDevice *device)
+ 
+ 	return !!priv->pending_actions;
+ }
++
++const char *
++nm_device_get_physical_port_id (NMDevice *device)
++{
++	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device);
++
++	return priv->physical_port_id;
++}
+diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
+index 38b9bea..b593d0a 100644
+--- a/src/devices/nm-device.h
++++ b/src/devices/nm-device.h
+@@ -60,6 +60,7 @@
+ #define NM_DEVICE_AUTOCONNECT      "autoconnect"
+ #define NM_DEVICE_FIRMWARE_MISSING "firmware-missing"
+ #define NM_DEVICE_AVAILABLE_CONNECTIONS "available-connections"
++#define NM_DEVICE_PHYSICAL_PORT_ID "physical-port-id"
+ #define NM_DEVICE_TYPE_DESC        "type-desc"    /* Internal only */
+ #define NM_DEVICE_RFKILL_TYPE      "rfkill-type"  /* Internal only */
+ #define NM_DEVICE_IFINDEX          "ifindex"      /* Internal only */
+@@ -337,6 +338,8 @@ gboolean nm_device_has_pending_action    (NMDevice *device);
+ void     nm_device_remove_pending_action (NMDevice *device, const char *action);
+ gboolean nm_device_has_pending_action    (NMDevice *device);
+ 
++const char *nm_device_get_physical_port_id (NMDevice *device);
++
+ G_END_DECLS
+ 
+ /* For testing only */
+diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
+index 6d7843f..491e23e 100644
+--- a/src/platform/nm-fake-platform.c
++++ b/src/platform/nm-fake-platform.c
+@@ -466,6 +466,15 @@ link_get_mtu (NMPlatform *platform, int ifindex)
+ 	return device ? device->link.mtu : 0;
+ }
+ 
++static char *
++link_get_physical_port_id (NMPlatform *platform, int ifindex)
++{
++	/* We call link_get just to cause an error to be set if @ifindex is bad. */
++	link_get (platform, ifindex);
++
++	return NULL;
++}
++
+ static gboolean
+ link_supports_carrier_detect (NMPlatform *platform, int ifindex)
+ {
+@@ -1189,6 +1198,8 @@ nm_fake_platform_class_init (NMFakePlatformClass *klass)
+ 	platform_class->link_get_mtu = link_get_mtu;
+ 	platform_class->link_set_mtu = link_set_mtu;
+ 
++	platform_class->link_get_physical_port_id = link_get_physical_port_id;
++
+ 	platform_class->link_supports_carrier_detect = link_supports_carrier_detect;
+ 	platform_class->link_supports_vlans = link_supports_vlans;
+ 
+diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
+index 821a8cd..23125f8 100644
+--- a/src/platform/nm-linux-platform.c
++++ b/src/platform/nm-linux-platform.c
+@@ -1725,6 +1725,26 @@ link_get_mtu (NMPlatform *platform, int ifindex)
+ 	return rtnllink ? rtnl_link_get_mtu (rtnllink) : 0;
+ }
+ 
++static char *
++link_get_physical_port_id (NMPlatform *platform, int ifindex)
++{
++	const char *ifname;
++	char *path, *id;
++
++	ifname = nm_platform_link_get_name (ifindex);
++	if (!ifname)
++		return NULL;
++
++	path = g_strdup_printf ("/sys/class/net/%s/physical_port_id", ifname);
++	if (g_file_test (path, G_FILE_TEST_EXISTS))
++		id = sysctl_get (platform, path);
++	else
++		id = NULL;
++	g_free (path);
++
++	return id;
++}
++
+ static int
+ vlan_add (NMPlatform *platform, const char *name, int parent, int vlan_id, guint32 vlan_flags)
+ {
+@@ -2719,6 +2739,8 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
+ 	platform_class->link_get_mtu = link_get_mtu;
+ 	platform_class->link_set_mtu = link_set_mtu;
+ 
++	platform_class->link_get_physical_port_id = link_get_physical_port_id;
++
+ 	platform_class->link_supports_carrier_detect = link_supports_carrier_detect;
+ 	platform_class->link_supports_vlans = link_supports_vlans;
+ 
+diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
+index f5a4c9b..7460b12 100644
+--- a/src/platform/nm-platform.c
++++ b/src/platform/nm-platform.c
+@@ -734,6 +734,24 @@ nm_platform_link_get_mtu (int ifindex)
+ }
+ 
+ /**
++ * nm_platform_link_get_mtu:
++ * @ifindex: Interface index
++ *
++ * Returns: physical port ID for the interface, or %NULL on error
++ * or if the interface has no physical port ID.
++ */
++char *
++nm_platform_link_get_physical_port_id (int ifindex)
++{
++	reset_error ();
++
++	g_return_val_if_fail (ifindex >= 0, NULL);
++	g_return_val_if_fail (klass->link_get_physical_port_id, NULL);
++
++	return klass->link_get_physical_port_id (platform, ifindex);
++}
++
++/**
+  * nm_platform_link_enslave:
+  * @master: Interface index of the master
+  * @slave: Interface index of the slave
+diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
+index b11bbc3..5494d48 100644
+--- a/src/platform/nm-platform.h
++++ b/src/platform/nm-platform.h
+@@ -251,6 +251,8 @@ typedef struct {
+ 	guint32 (*link_get_mtu) (NMPlatform *, int ifindex);
+ 	gboolean (*link_set_mtu) (NMPlatform *, int ifindex, guint32 mtu);
+ 
++	char * (*link_get_physical_port_id) (NMPlatform *, int ifindex);
++
+ 	gboolean (*link_supports_carrier_detect) (NMPlatform *, int ifindex);
+ 	gboolean (*link_supports_vlans) (NMPlatform *, int ifindex);
+ 
+@@ -370,6 +372,8 @@ gboolean nm_platform_link_set_address (int ifindex, const void *address, size_t
+ guint32 nm_platform_link_get_mtu (int ifindex);
+ gboolean nm_platform_link_set_mtu (int ifindex, guint32 mtu);
+ 
++char *nm_platform_link_get_physical_port_id (int ifindex);
++
+ gboolean nm_platform_link_supports_carrier_detect (int ifindex);
+ gboolean nm_platform_link_supports_vlans (int ifindex);
+ 
+-- 
+1.7.11.7
+
+
+From 47cc8b25f2efe015defde7e76e49e67086603bb3 Mon Sep 17 00:00:00 2001
+From: Dan Winship <danw at gnome.org>
+Date: Fri, 11 Oct 2013 14:59:26 -0400
+Subject: [PATCH 2/2] libnm-glib: add NMDevice:physical-port-id property
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add the physical-port-id property to NMDevice so that clients can
+recognize NPAR/SR-IOV devices.
+
+Signed-off-by: Jiří Klimeš <jklimes at redhat.com>
+---
+ libnm-glib/libnm-glib.ver |  1 +
+ libnm-glib/nm-device.c    | 55 +++++++++++++++++++++++++++++++++++++++++++++++
+ libnm-glib/nm-device.h    |  2 ++
+ 3 files changed, 58 insertions(+)
+
+diff --git a/libnm-glib/libnm-glib.ver b/libnm-glib/libnm-glib.ver
+index 4727bc3..416b782 100644
+--- a/libnm-glib/libnm-glib.ver
++++ b/libnm-glib/libnm-glib.ver
+@@ -130,6 +130,7 @@ global:
+ 	nm_device_get_ip6_config;
+ 	nm_device_get_ip_iface;
+ 	nm_device_get_managed;
++	nm_device_get_physical_port_id;
+ 	nm_device_get_product;
+ 	nm_device_get_state;
+ 	nm_device_get_state_reason;
+diff --git a/libnm-glib/nm-device.c b/libnm-glib/nm-device.c
+index 05e59e5..d4f95ac 100644
+--- a/libnm-glib/nm-device.c
++++ b/libnm-glib/nm-device.c
+@@ -96,6 +96,8 @@ typedef struct {
+ 	GUdevClient *client;
+ 	char *product;
+ 	char *vendor;
++
++	char *physical_port_id;
+ } NMDevicePrivate;
+ 
+ enum {
+@@ -121,6 +123,7 @@ enum {
+ 	PROP_DEVICE_TYPE,
+ 	PROP_ACTIVE_CONNECTION,
+ 	PROP_AVAILABLE_CONNECTIONS,
++	PROP_PHYSICAL_PORT_ID,
+ 
+ 	LAST_PROP
+ };
+@@ -199,6 +202,7 @@ register_properties (NMDevice *device)
+ 		{ NM_DEVICE_STATE_REASON,      &priv->state, demarshal_state_reason },
+ 		{ NM_DEVICE_ACTIVE_CONNECTION, &priv->active_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
+ 		{ NM_DEVICE_AVAILABLE_CONNECTIONS, &priv->available_connections, NULL, NM_TYPE_REMOTE_CONNECTION },
++		{ NM_DEVICE_PHYSICAL_PORT_ID,  &priv->physical_port_id },
+ 
+ 		/* Properties that exist in D-Bus but that we don't track */
+ 		{ "ip4-address", NULL },
+@@ -389,6 +393,7 @@ finalize (GObject *object)
+ 	g_free (priv->product);
+ 	g_free (priv->vendor);
+ 	g_free (priv->type_description);
++	g_free (priv->physical_port_id);
+ 
+ 	G_OBJECT_CLASS (nm_device_parent_class)->finalize (object);
+ }
+@@ -473,6 +478,9 @@ get_property (GObject *object,
+ 	case PROP_VENDOR:
+ 		g_value_set_string (value, nm_device_get_vendor (device));
+ 		break;
++	case PROP_PHYSICAL_PORT_ID:
++		g_value_set_string (value, nm_device_get_physical_port_id (device));
++		break;
+ 	default:
+ 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ 		break;
+@@ -804,6 +812,22 @@ nm_device_class_init (NMDeviceClass *device_class)
+ 						  NULL,
+ 						  G_PARAM_READABLE));
+ 
++	/**
++	 * NMDevice:physical-port-id:
++	 *
++	 * The physical port ID of the device. (See
++	 * nm_device_get_physical_port_id().)
++	 *
++	 * Since: 0.9.10
++	 **/
++	g_object_class_install_property
++		(object_class, PROP_PHYSICAL_PORT_ID,
++		 g_param_spec_string (NM_DEVICE_PHYSICAL_PORT_ID,
++		                      "Physical Port ID",
++		                      "Physical port ID",
++		                      NULL,
++		                      G_PARAM_READABLE));
++
+ 	/* signals */
+ 
+ 	/**
+@@ -1517,6 +1541,37 @@ nm_device_get_vendor (NMDevice *device)
+ 	return priv->vendor;
+ }
+ 
++/**
++ * nm_device_get_physical_port_id:
++ * @device: a #NMDevice
++ *
++ * Gets the physical port ID of the #NMDevice. If non-%NULL, this is
++ * an opaque string that can be used to recognize when
++ * seemingly-unrelated #NMDevices are actually just different virtual
++ * ports on a single physical port. (Eg, NPAR / SR-IOV.)
++ *
++ * Returns: the physical port ID of the device, or %NULL if the port
++ *   ID is unknown. This is the internal string used by the device and
++ *   must not be modified.
++ *
++ * Since: 0.9.10
++ **/
++const char *
++nm_device_get_physical_port_id (NMDevice *device)
++{
++	NMDevicePrivate *priv;
++
++	g_return_val_if_fail (NM_IS_DEVICE (device), NULL);
++
++	priv = NM_DEVICE_GET_PRIVATE (device);
++
++	_nm_object_ensure_inited (NM_OBJECT (device));
++	if (priv->physical_port_id && *priv->physical_port_id)
++		return priv->physical_port_id;
++	else
++		return NULL;
++}
++
+ typedef struct {
+ 	NMDevice *device;
+ 	NMDeviceDeactivateFn fn;
+diff --git a/libnm-glib/nm-device.h b/libnm-glib/nm-device.h
+index ed274ca..bd746b3 100644
+--- a/libnm-glib/nm-device.h
++++ b/libnm-glib/nm-device.h
+@@ -80,6 +80,7 @@ GQuark nm_device_error_quark (void);
+ #define NM_DEVICE_AVAILABLE_CONNECTIONS "available-connections"
+ #define NM_DEVICE_VENDOR "vendor"
+ #define NM_DEVICE_PRODUCT "product"
++#define NM_DEVICE_PHYSICAL_PORT_ID "physical-port-id"
+ 
+ typedef struct {
+ 	NMObject parent;
+@@ -135,6 +136,7 @@ NMActiveConnection * nm_device_get_active_connection(NMDevice *device);
+ const GPtrArray *    nm_device_get_available_connections(NMDevice *device);
+ const char *         nm_device_get_product          (NMDevice *device);
+ const char *         nm_device_get_vendor           (NMDevice *device);
++const char *         nm_device_get_physical_port_id (NMDevice *device);
+ 
+ typedef void (*NMDeviceDeactivateFn) (NMDevice *device, GError *error, gpointer user_data);
+ 
+-- 
+1.7.11.7
+


More information about the scm-commits mailing list