Schema versioning and evolution
by David Lutterkort
One of the things that I'd like to settle on before declaring the
interface schema (in data/xml/interface.rng) final, is how to handle
schema versioning and schema evolution.
The schema will only be allowed to evolve in a way that is backwards
compatible: if an interface.xml is valid against version N of
interface.rng, it has to remain valid against all future versions. That
implies that changes to the schema can only add to it, never take away.
Sometimes it's desirable though to see whether an interface.xml is valid
against some older version of the schema; to facilitate that, I am
thinking of annotating interface.rng with version information:
* versions are simple integers, that only increase
* put version annotiation into a 'version' namespace (say
http://netcf.org/xml/version/1.0)
* add a 'version:serial' attribute to the start tag in
interface.rng. This indicates the current version of
interface.rng
* add a 'version:since' attribute on constructs that are
introduced in later revisions of the schema
With that, if we have version 7 of interface.rng, we can reproduce the
schema for version 5 by removing any tags (and their contents) from the
RelaxNG that have a version:since > 5.
This should work well for adding elements, attributes, expanding the
list of allowed values for existing attributes etc. and introduces very
little overhead.
Any thoughts on this ?
David
14 years, 10 months
VLAN interfaces (take 2)
by David Lutterkort
This is the second take on adding vlan interfaces. The format has been
changed according to Dan's suggestion, so that a bridge with an enslaved
VLAN now looks like
<interface type="bridge" name="br0">
<start mode="onboot"/>
<protocol family="ipv4">
<dhcp/>
</protocol>
<bridge stp="off">
<interface type="vlan" name="eth0.42">
<vlan tag="42">
<interface name="eth0"/>
</vlan>
</interface>
</bridge>
</interface>
Besides changing the way how the base interface for a VLAN interface is
expressed (with the nested <vlan/>) tag, these patches have also been
rebased to work with the changes for interface/@name and interface/start
that I just posted.
I'll probably commit these in the next few hours, since I won't be around
tomorrow, so people can follow along more easily at home.
David
14 years, 10 months
[PATCH 1/1] schema: change interface naming and startmode
by David Lutterkort
We now put the name of an interface into the name attribute of the
interface element. The startmode is now a separate element, not an
attribute on <interface/>
---
data/xml/initscripts-get.xsl | 32 +++++++++++-------
data/xml/initscripts-put.xsl | 44 ++++++++++++++----------
data/xml/interface.rng | 36 ++++++++++++--------
tests/initscripts/bridge.xml | 4 +-
tests/initscripts/ethernet-dhcp.xml | 2 +-
tests/interface/bond-arp.xml | 12 ++----
tests/interface/bond.xml | 12 ++----
tests/interface/bridge.xml | 13 +++----
tests/interface/ethernet-dhcp.xml | 6 ++--
tests/interface/ethernet-static-no-prefix.xml | 4 +-
tests/interface/ethernet-static.xml | 4 +-
11 files changed, 90 insertions(+), 79 deletions(-)
diff --git a/data/xml/initscripts-get.xsl b/data/xml/initscripts-get.xsl
index e0058c2..dc6318f 100644
--- a/data/xml/initscripts-get.xsl
+++ b/data/xml/initscripts-get.xsl
@@ -28,9 +28,10 @@
-->
<xsl:template match="/interface[@type = 'bridge']">
<tree>
- <xsl:call-template name="basic-attrs"/>
- <node label="TYPE" value="Bridge"/>
+ <xsl:call-template name="name-attr"/>
<xsl:call-template name="startmode"/>
+ <xsl:call-template name="mtu"/>
+ <node label="TYPE" value="Bridge"/>
<xsl:call-template name="interface-addressing"/>
<xsl:if test="bridge/@stp">
<node label="STP" value="{bridge/@stp}"/>
@@ -39,7 +40,7 @@
<xsl:for-each select='bridge/interface'>
<tree>
<xsl:call-template name="bare-ethernet-interface"/>
- <node label="BRIDGE" value="{../../name}"/>
+ <node label="BRIDGE" value="{../../@name}"/>
</tree>
</xsl:for-each>
</xsl:template>
@@ -49,14 +50,15 @@
-->
<xsl:template match="/interface[@type = 'bond']">
<tree>
- <xsl:call-template name="basic-attrs"/>
+ <xsl:call-template name="name-attr"/>
<xsl:call-template name="startmode"/>
+ <xsl:call-template name="mtu"/>
<xsl:call-template name="interface-addressing"/>
<node label="BONDING_OPTS">
<xsl:attribute name="value">
<xsl:text>'</xsl:text>
<xsl:if test="bond/@mode">mode=<xsl:value-of select='bond/@mode'/></xsl:if>
- <xsl:if test="bond/@mode = 'active-backup'"> primary=<xsl:value-of select='bond/interface[1]/name'/></xsl:if>
+ <xsl:if test="bond/@mode = 'active-backup'"> primary=<xsl:value-of select='bond/interface[1]/@name'/></xsl:if>
<xsl:if test="bond/miimon">
<xsl:text> miimon=</xsl:text><xsl:value-of select='bond/miimon/@freq'/>
<xsl:if test="bond/miimon/@downdelay"><xsl:text> downdelay=</xsl:text><xsl:value-of select="bond/miimon/@downdelay"/></xsl:if>
@@ -79,7 +81,7 @@
<xsl:for-each select='bond/interface'>
<tree>
<xsl:call-template name="bare-ethernet-interface"/>
- <node label="MASTER" value="{../../name}"/>
+ <node label="MASTER" value="{../../@name}"/>
<node label="SLAVE" value="yes"/>
</tree>
</xsl:for-each>
@@ -88,30 +90,34 @@
<!--
Named templates, following the Relax NG syntax
-->
- <xsl:template name="basic-attrs">
- <xsl:attribute name="path">/files/etc/sysconfig/network-scripts/ifcfg-<xsl:value-of select="name"/></xsl:attribute>
- <node label="DEVICE" value="{name}"/>
+ <xsl:template name="name-attr">
+ <xsl:attribute name="path">/files/etc/sysconfig/network-scripts/ifcfg-<xsl:value-of select="@name"/></xsl:attribute>
+ <node label="DEVICE" value="{@name}"/>
+ </xsl:template>
+
+ <xsl:template name="mtu">
<xsl:if test="mtu">
<node label="MTU" value="{mtu/@size}"/>
</xsl:if>
</xsl:template>
<xsl:template name="bare-ethernet-interface">
- <xsl:call-template name="basic-attrs"/>
+ <xsl:call-template name="name-attr"/>
<xsl:if test="mac">
<node label="HWADDR" value="{mac/@address}"/>
</xsl:if>
+ <xsl:call-template name="mtu"/>
</xsl:template>
<xsl:template name="startmode">
<xsl:choose>
- <xsl:when test="@startmode = 'onboot'">
+ <xsl:when test="start/@mode = 'onboot'">
<node label="ONBOOT" value="yes"/>
</xsl:when>
- <xsl:when test="@startmode = 'none'">
+ <xsl:when test="start/@mode = 'none'">
<node label="ONBOOT" value="no"/>
</xsl:when>
- <xsl:when test="@startmode = 'hotplug'">
+ <xsl:when test="start/@mode = 'hotplug'">
<node label="ONBOOT" value="no"/>
<node label="HOTPLUG" value="yes"/>
</xsl:when>
diff --git a/data/xml/initscripts-put.xsl b/data/xml/initscripts-put.xsl
index 74d7057..3c1114e 100644
--- a/data/xml/initscripts-put.xsl
+++ b/data/xml/initscripts-put.xsl
@@ -18,8 +18,12 @@
<xsl:template name="ethernet-interface"
match="tree[count(node[@label = 'MASTER' or @label='BRIDGE']) = 0]">
<interface type="ethernet">
+ <xsl:call-template name="name-attr"/>
<xsl:call-template name="startmode"/>
- <xsl:call-template name="basic-ethernet-content"/>
+ <xsl:if test="node[@label = 'HWADDR']">
+ <mac address="{node[@label = 'HWADDR']/@value}"/>
+ </xsl:if>
+ <xsl:call-template name="mtu"/>
<xsl:call-template name="interface-addressing"/>
</interface>
</xsl:template>
@@ -31,9 +35,10 @@
match="tree[node[@label = 'TYPE' and @value = 'Bridge']]">
<interface type="bridge">
<!-- the bridge node itself -->
- <xsl:call-template name="startmode"/>
<xsl:variable name="iface" select="node[@label= 'DEVICE']/@value"/>
- <xsl:call-template name="basic-attrs"/>
+ <xsl:call-template name="name-attr"/>
+ <xsl:call-template name="startmode"/>
+ <xsl:call-template name="mtu"/>
<xsl:call-template name="interface-addressing"/>
<bridge>
<xsl:if test="node[@label = 'STP']">
@@ -52,9 +57,10 @@
<xsl:template name="bond-interface"
match="tree[node[@label = 'DEVICE'][@value = //tree/node[@label = 'MASTER']/@value]]">
<interface type="bond">
- <xsl:call-template name="startmode"/>
<xsl:variable name="iface" select="node[@label= 'DEVICE']/@value"/>
- <xsl:call-template name="basic-attrs"/>
+ <xsl:call-template name="name-attr"/>
+ <xsl:call-template name="startmode"/>
+ <xsl:call-template name="mtu"/>
<xsl:call-template name="interface-addressing"/>
<bond>
<xsl:variable name="opts" select="node[@label = 'BONDING_OPTS']/@value"/>
@@ -106,19 +112,24 @@
<xsl:template name="startmode">
<xsl:choose>
<xsl:when test="node[@label ='HOTPLUG']/@value = 'yes'">
- <xsl:attribute name="startmode">hotplug</xsl:attribute>
+ <start mode='hotplug'/>
</xsl:when>
<xsl:when test="node[@label = 'ONBOOT']/@value = 'yes'">
- <xsl:attribute name="startmode">onboot</xsl:attribute>
+ <start mode='onboot'/>
</xsl:when>
<xsl:otherwise>
- <xsl:attribute name="startmode">none</xsl:attribute>
+ <start mode='none'/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
- <xsl:template name="basic-attrs">
- <name><xsl:value-of select="node[@label= 'DEVICE']/@value"/></name>
+ <xsl:template name="name-attr">
+ <xsl:attribute name="name">
+ <xsl:value-of select="node[@label= 'DEVICE']/@value"/>
+ </xsl:attribute>
+ </xsl:template>
+
+ <xsl:template name="mtu">
<xsl:if test="node[@label='MTU']">
<mtu size="{node[@label='MTU']/@value}"/>
</xsl:if>
@@ -152,16 +163,13 @@
</protocol>
</xsl:template>
- <xsl:template name="basic-ethernet-content">
- <xsl:call-template name="basic-attrs"/>
- <xsl:if test="node[@label = 'HWADDR']">
- <mac address="{node[@label = 'HWADDR']/@value}"/>
- </xsl:if>
- </xsl:template>
-
<xsl:template name="bare-ethernet-interface">
<interface type="ethernet">
- <xsl:call-template name="basic-ethernet-content"/>
+ <xsl:call-template name="name-attr"/>
+ <xsl:if test="node[@label = 'HWADDR']">
+ <mac address="{node[@label = 'HWADDR']/@value}"/>
+ </xsl:if>
+ <xsl:call-template name="mtu"/>
</interface>
</xsl:template>
</xsl:stylesheet>
diff --git a/data/xml/interface.rng b/data/xml/interface.rng
index 2afc824..3fd5532 100644
--- a/data/xml/interface.rng
+++ b/data/xml/interface.rng
@@ -23,7 +23,7 @@
<attribute name="type">
<value>ethernet</value>
</attribute>
- <ref name="basic-attrs"/>
+ <ref name="name-attr"/>
<!-- If no MAC is given when the interface is defined, it is determined
by using the device name.
FIXME: What if device name and MAC don't specify the same NIC ? -->
@@ -32,6 +32,7 @@
<attribute name="address"><ref name="mac-addr"/></attribute>
</element>
</optional>
+ <ref name="mtu"/>
<!-- FIXME: Allow (some) ethtool options -->
</define>
@@ -58,8 +59,9 @@
<attribute name="type">
<value>bridge</value>
</attribute>
+ <ref name="name-attr"/>
<ref name="startmode"/>
- <ref name="basic-attrs"/>
+ <ref name="mtu"/>
<ref name="interface-addressing"/>
<element name="bridge">
<optional>
@@ -85,8 +87,9 @@
<attribute name="type">
<value>bond</value>
</attribute>
+ <ref name="name-attr"/>
<ref name="startmode"/>
- <ref name="basic-attrs"/>
+ <ref name="mtu"/>
<ref name="interface-addressing"/>
<element name="bond">
<optional>
@@ -167,9 +170,12 @@
</define>
<!-- Basic attributes for all interface types -->
- <define name="basic-attrs">
+ <define name="name-attr">
<!-- The device name, like eth0 or br2 -->
- <element name="name"><ref name="device-name"/></element>
+ <attribute name="name"><ref name="device-name"/></attribute>
+ </define>
+
+ <define name="mtu">
<optional>
<element name="mtu">
<attribute name="size"><ref name="uint"/></attribute>
@@ -178,15 +184,17 @@
</define>
<define name="startmode">
- <attribute name="startmode">
- <choice>
- <value>onboot</value>
- <value>none</value>
- <value>hotplug</value>
- <!-- Jim Fehlig lists the following that SuSe supports:
- manual, ifplug, nfsroot -->
- </choice>
- </attribute>
+ <element name="start">
+ <attribute name="mode">
+ <choice>
+ <value>onboot</value>
+ <value>none</value>
+ <value>hotplug</value>
+ <!-- Jim Fehlig lists the following that SuSe supports:
+ manual, ifplug, nfsroot -->
+ </choice>
+ </attribute>
+ </element>
</define>
<!--
diff --git a/tests/initscripts/bridge.xml b/tests/initscripts/bridge.xml
index 7826aae..01acf19 100644
--- a/tests/initscripts/bridge.xml
+++ b/tests/initscripts/bridge.xml
@@ -5,16 +5,16 @@
<forest>
<tree path="/files/etc/sysconfig/network-scripts/ifcfg-br0">
<node label="DEVICE" value="br0"/>
+ <node label="ONBOOT" value="yes"/>
<node label="MTU" value="1500"/>
<node label="TYPE" value="Bridge"/>
- <node label="ONBOOT" value="yes"/>
<node label="BOOTPROTO" value="dhcp"/>
<node label="STP" value="off"/>
</tree>
<tree path="/files/etc/sysconfig/network-scripts/ifcfg-eth0">
<node label="DEVICE" value="eth0"/>
- <node label="MTU" value="1492"/>
<node label="HWADDR" value="ab:bb:cc:dd:ee:ff"/>
+ <node label="MTU" value="1492"/>
<node label="BRIDGE" value="br0"/>
</tree>
<tree path="/files/etc/sysconfig/network-scripts/ifcfg-eth1">
diff --git a/tests/initscripts/ethernet-dhcp.xml b/tests/initscripts/ethernet-dhcp.xml
index f26bcd2..8233509 100644
--- a/tests/initscripts/ethernet-dhcp.xml
+++ b/tests/initscripts/ethernet-dhcp.xml
@@ -5,8 +5,8 @@
<forest>
<tree path="/files/etc/sysconfig/network-scripts/ifcfg-eth0">
<node label="DEVICE" value="eth0"/>
- <node label="MTU" value="1492"/>
<node label="HWADDR" value="aa:bb:cc:dd:ee:ff"/>
+ <node label="MTU" value="1492"/>
<node label="ONBOOT" value="no"/>
<node label="BOOTPROTO" value="dhcp"/>
<node label="PEERDNS" value="no"/>
diff --git a/tests/interface/bond-arp.xml b/tests/interface/bond-arp.xml
index 1206b1b..13154ec 100644
--- a/tests/interface/bond-arp.xml
+++ b/tests/interface/bond-arp.xml
@@ -1,16 +1,12 @@
-<interface type="bond" startmode="none">
- <name>bond0</name>
+<interface type="bond" name="bond0">
+ <start mode="none"/>
<protocol family="ipv4">
<ip address="192.168.50.7" prefix="24"/>
<route gateway="192.168.50.1"/>
</protocol>
<bond mode="active-backup">
<arpmon interval="100" target="192.168.50.1" validate="active"/>
- <interface type="ethernet">
- <name>eth1</name>
- </interface>
- <interface type="ethernet">
- <name>eth0</name>
- </interface>
+ <interface type="ethernet" name="eth1"/>
+ <interface type="ethernet" name="eth0"/>
</bond>
</interface>
diff --git a/tests/interface/bond.xml b/tests/interface/bond.xml
index 640ad52..d4025f4 100644
--- a/tests/interface/bond.xml
+++ b/tests/interface/bond.xml
@@ -1,16 +1,12 @@
-<interface type="bond" startmode="none">
- <name>bond0</name>
+<interface type="bond" name="bond0">
+ <start mode="none"/>
<protocol family="ipv4">
<ip address="192.168.50.7" prefix="24"/>
<route gateway="192.168.50.1"/>
</protocol>
<bond mode="active-backup">
<miimon freq="100" updelay="10" carrier="ioctl"/>
- <interface type="ethernet">
- <name>eth1</name>
- </interface>
- <interface type="ethernet">
- <name>eth0</name>
- </interface>
+ <interface type="ethernet" name="eth1"/>
+ <interface type="ethernet" name="eth0"/>
</bond>
</interface>
diff --git a/tests/interface/bridge.xml b/tests/interface/bridge.xml
index 583dcf6..e309060 100644
--- a/tests/interface/bridge.xml
+++ b/tests/interface/bridge.xml
@@ -1,19 +1,16 @@
-<interface type="bridge" startmode="onboot">
- <name>br0</name>
+<interface type="bridge" name="br0">
+ <start mode="onboot"/>
<mtu size="1500"/>
<protocol family="ipv4">
<dhcp/>
</protocol>
<bridge stp="off">
- <interface type="ethernet">
- <name>eth0</name>
+ <interface type="ethernet" name="eth0">
<!-- FIXME: is it reasonable to alllow separate MTU's for bridge and
enslaved if ? -->
- <mtu size="1492"/>
<mac address="ab:bb:cc:dd:ee:ff"/>
+ <mtu size="1492"/>
</interface>
- <interface type="ethernet">
- <name>eth1</name>
- </interface>
+ <interface type="ethernet" name="eth1"/>
</bridge>
</interface>
diff --git a/tests/interface/ethernet-dhcp.xml b/tests/interface/ethernet-dhcp.xml
index 66b91de..1d5a03d 100644
--- a/tests/interface/ethernet-dhcp.xml
+++ b/tests/interface/ethernet-dhcp.xml
@@ -1,7 +1,7 @@
-<interface type="ethernet" startmode="none">
- <name>eth0</name>
- <mtu size="1492"/>
+<interface type="ethernet" name="eth0">
+ <start mode="none"/>
<mac address="aa:bb:cc:dd:ee:ff"/>
+ <mtu size="1492"/>
<protocol family="ipv4">
<dhcp peerdns="no"/>
</protocol>
diff --git a/tests/interface/ethernet-static-no-prefix.xml b/tests/interface/ethernet-static-no-prefix.xml
index a578677..476e9f3 100644
--- a/tests/interface/ethernet-static-no-prefix.xml
+++ b/tests/interface/ethernet-static-no-prefix.xml
@@ -1,5 +1,5 @@
-<interface type="ethernet" startmode="onboot">
- <name>eth1</name>
+<interface type="ethernet" name="eth1">
+ <start mode="onboot"/>
<protocol family="ipv4">
<ip address="192.168.0.5"/>
<route gateway="192.168.0.1"/>
diff --git a/tests/interface/ethernet-static.xml b/tests/interface/ethernet-static.xml
index eb285f6..3ba3e11 100644
--- a/tests/interface/ethernet-static.xml
+++ b/tests/interface/ethernet-static.xml
@@ -1,5 +1,5 @@
-<interface type="ethernet" startmode="onboot">
- <name>eth1</name>
+<interface type="ethernet" name="eth1">
+ <start mode="onboot"/>
<protocol family="ipv4">
<ip address="192.168.0.5" prefix="24"/>
<route gateway="192.168.0.1"/>
--
1.6.0.6
14 years, 10 months
[PATCH] (take 3) Add active/inactive flag to ncf_num_of_interfaces() & ncf_list_interfaces().
by Laine Stump
This is a rebase of the previous submission, plus changing the name of
the flags slightly, closing ioctl_fd if there's an error in drv_init,
and fixing the flag naming in test-initscripts.c (all suggested by
lutter in IRC just now)
---
src/drv_initscripts.c | 101 ++++++++++++++++++++++++++++++++++++++-------
src/internal.h | 4 +-
src/ncftool.c | 16 ++++++-
src/netcf.c | 8 ++--
src/netcf.h | 21 +++++++---
tests/test-initscripts.c | 4 +-
6 files changed, 122 insertions(+), 32 deletions(-)
diff --git a/src/drv_initscripts.c b/src/drv_initscripts.c
index d0a9af8..c63dc90 100644
--- a/src/drv_initscripts.c
+++ b/src/drv_initscripts.c
@@ -30,6 +30,11 @@
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+
#include "safe-alloc.h"
#include "ref.h"
#include "list.h"
@@ -86,6 +91,7 @@ struct driver {
xsltStylesheetPtr put;
xsltStylesheetPtr get;
xmlRelaxNGPtr rng;
+ int ioctl_fd;
};
/* Entries in a ifcfg file that tell us that the interface
@@ -214,6 +220,18 @@ static int is_slave(struct netcf *ncf, const char *intf) {
return 0;
}
+static int is_active(struct netcf *ncf, const char *intf) {
+ struct ifreq ifr;
+
+ MEMZERO(&ifr, 1);
+ strncpy(ifr.ifr_name, intf, sizeof(ifr.ifr_name));
+ ifr.ifr_name[sizeof(ifr.ifr_name)] = '\0';
+ if (ioctl(ncf->driver->ioctl_fd, SIOCGIFFLAGS, &ifr)) {
+ return 0;
+ }
+ return ((ifr.ifr_flags & IFF_UP) == IFF_UP);
+}
+
static int list_interfaces(struct netcf *ncf, char ***intf) {
int nint = 0, result = 0;
struct augeas *aug = NULL;
@@ -422,11 +440,35 @@ static char *xml_prop(xmlNodePtr node, const char *name) {
return (char *) xmlGetProp(node, BAD_CAST name);
}
+static int init_ioctl_fd(struct netcf *ncf) {
+
+ int ioctl_fd;
+ int flags;
+
+ ioctl_fd = socket(AF_INET, SOCK_STREAM, 0);
+ ERR_THROW(ioctl_fd < 0, ncf, EINTERNAL, "failed to open socket for interface ioctl");
+
+ flags = fcntl(ioctl_fd, F_GETFD);
+ ERR_THROW(flags < 0, ncf, EINTERNAL, "failed to get flags for ioctl socket");
+
+ flags = fcntl(ioctl_fd, F_SETFD, flags | FD_CLOEXEC);
+ ERR_THROW(flags < 0, ncf, EINTERNAL, "failed to set FD_CLOEXEC flag on ioctl socket");
+ return ioctl_fd;
+
+error:
+ if (ioctl_fd >= 0)
+ close(ioctl_fd);
+ return -1;
+}
+
int drv_init(struct netcf *ncf) {
int r;
if (ALLOC(ncf->driver) < 0)
return -1;
+
+ ncf->driver->ioctl_fd = -1;
+
// FIXME: Check for errors
xsltInit();
r = xslt_ext_register();
@@ -436,8 +478,16 @@ int drv_init(struct netcf *ncf) {
ncf->driver->rng = rng_parse(ncf, "interface.rng");
/* We undconditionally bridge physdevs; could be more discriminating */
bridge_physdevs(ncf);
+
+ /* open a socket for interface ioctls */
+ ncf->driver->ioctl_fd = init_ioctl_fd(ncf);
+ if (ncf->driver->ioctl_fd < 0)
+ goto error;
return 0;
+
error:
+ if (ncf->driver->ioctl_fd >= 0)
+ close(ncf->driver->ioctl_fd);
FREE(ncf->driver);
return -1;
}
@@ -447,49 +497,68 @@ void drv_close(struct netcf *ncf) {
xsltFreeStylesheet(ncf->driver->put);
xslt_ext_unregister();
xsltCleanupGlobals();
+ if (ncf->driver->ioctl_fd >= 0)
+ close(ncf->driver->ioctl_fd);
FREE(ncf->driver);
}
-int drv_num_of_interfaces(struct netcf *ncf) {
- int nint = 0;
- char **intf = NULL;
-
- nint = list_interfaces(ncf, &intf);
- free_matches(nint, &intf);
- return nint;
-}
-
static int list_interface_ids(struct netcf *ncf,
int maxnames, char **names,
+ unsigned int flags,
const char *id_attr) {
struct augeas *aug = NULL;
- int nint = 0, nmatches = 0, result = 0, r;
+ int nint = 0, nmatches = 0, nqualified = 0, result = 0, r;
char **intf = NULL, **matches = NULL;
aug = get_augeas(ncf);
ERR_BAIL(ncf);
nint = list_interfaces(ncf, &intf);
- for (result = 0; result < nint && result < maxnames; result++) {
+ if (!names) {
+ maxnames = nint; /* if not returning list, ignore maxnames too */
+ }
+ for (result = 0; (result < nint) && (nqualified < maxnames); result++) {
nmatches = aug_submatch(ncf, intf[result], id_attr, &matches);
if (nmatches > 0) {
const char *name;
+ int is_qualified = ((flags & (NETCF_IFACE_ACTIVE|NETCF_IFACE_INACTIVE))
+ == (NETCF_IFACE_ACTIVE|NETCF_IFACE_INACTIVE));
+
r = aug_get(aug, matches[nmatches-1], &name);
ERR_COND_BAIL(r < 0, ncf, EOTHER);
- names[result] = strdup(name);
- ERR_COND_BAIL(names[result] == NULL, ncf, ENOMEM);
+
+ if (!is_qualified) {
+ int if_is_active = is_active(ncf, name);
+ if ((if_is_active && (flags & NETCF_IFACE_ACTIVE))
+ || ((!if_is_active) && (flags & NETCF_IFACE_INACTIVE))) {
+
+ is_qualified = 1;
+ }
+ }
+
+ if (is_qualified) {
+ if (names) {
+ names[nqualified] = strdup(name);
+ ERR_COND_BAIL(names[nqualified] == NULL, ncf, ENOMEM);
+ }
+ nqualified++;
+ }
}
free_matches(nmatches, &matches);
}
free_matches(nint, &intf);
- return result;
+ return nqualified;
error:
free_matches(nmatches, &matches);
free_matches(nint, &intf);
return -1;
}
-int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names) {
- return list_interface_ids(ncf, maxnames, names, "DEVICE");
+int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names, unsigned int flags) {
+ return list_interface_ids(ncf, maxnames, names, flags, "DEVICE");
+}
+
+int drv_num_of_interfaces(struct netcf *ncf, unsigned int flags) {
+ return list_interface_ids(ncf, 0, NULL, flags, "DEVICE");
}
static struct netcf_if *make_netcf_if(struct netcf *ncf, char *name) {
diff --git a/src/internal.h b/src/internal.h
index dc10a62..56c6038 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -152,8 +152,8 @@ void vreport_error(struct netcf *ncf, netcf_errcode_t errcode,
*/
int drv_init(struct netcf *netcf);
void drv_close(struct netcf *netcf);
-int drv_num_of_interfaces(struct netcf *ncf);
-int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names);
+int drv_num_of_interfaces(struct netcf *ncf, unsigned int flags);
+int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names, unsigned int flags);
struct netcf_if *drv_lookup_by_name(struct netcf *ncf, const char *name);
int drv_lookup_by_mac_string(struct netcf *, const char *mac,
int maxifaces, struct netcf_if **ifaces);
diff --git a/src/ncftool.c b/src/ncftool.c
index cee1fce..a1362c2 100644
--- a/src/ncftool.c
+++ b/src/ncftool.c
@@ -137,13 +137,21 @@ static const char *arg_value(const struct command *cmd, const char *name) {
static int cmd_list(ATTRIBUTE_UNUSED const struct command *cmd) {
int nint;
char **intf;
+ unsigned int flags = NETCF_IFACE_ACTIVE;
- nint = ncf_num_of_interfaces(ncf);
+ if (opt_present(cmd, "inactive")) {
+ flags = NETCF_IFACE_INACTIVE;
+ }
+ if (opt_present(cmd, "all")) {
+ flags = NETCF_IFACE_ACTIVE | NETCF_IFACE_INACTIVE;
+ }
+
+ nint = ncf_num_of_interfaces(ncf, flags);
if (nint < 0)
return CMD_RES_ERR;
if (ALLOC_N(intf, nint) < 0)
return CMD_RES_ENOMEM;
- nint = ncf_list_interfaces(ncf, nint, intf);
+ nint = ncf_list_interfaces(ncf, nint, intf, flags);
if (nint < 0)
return CMD_RES_ERR;
for (int i=0; i < nint; i++) {
@@ -175,6 +183,10 @@ static int cmd_list(ATTRIBUTE_UNUSED const struct command *cmd) {
static const struct command_opt_def cmd_list_opts[] = {
{ .tag = CMD_OPT_BOOL, .name = "macs",
.help = "show MAC addresses" },
+ { .tag = CMD_OPT_BOOL, .name = "all",
+ .help = "show all (up & down) interfaces" },
+ { .tag = CMD_OPT_BOOL, .name = "inactive",
+ .help = "show only inactive (down) interfaces" },
CMD_OPT_DEF_LAST
};
diff --git a/src/netcf.c b/src/netcf.c
index 4d9943c..906db7d 100644
--- a/src/netcf.c
+++ b/src/netcf.c
@@ -102,17 +102,17 @@ void ncf_close(struct netcf *ncf) {
*
* Maybe we should just list them as STRUCT NETCF_IF *
*/
-int ncf_num_of_interfaces(struct netcf *ncf) {
+int ncf_num_of_interfaces(struct netcf *ncf, unsigned int flags) {
ERR_RESET(ncf);
- return drv_num_of_interfaces(ncf);
+ return drv_num_of_interfaces(ncf, flags);
}
-int ncf_list_interfaces(struct netcf *ncf, int maxnames, char **names) {
+int ncf_list_interfaces(struct netcf *ncf, int maxnames, char **names, unsigned int flags) {
int result;
ERR_RESET(ncf);
MEMZERO(names, maxnames);
- result = drv_list_interfaces(ncf, maxnames, names);
+ result = drv_list_interfaces(ncf, maxnames, names, flags);
if (result < 0)
for (int i=0; i < maxnames; i++)
FREE(names[i]);
diff --git a/src/netcf.h b/src/netcf.h
index 377b196..c7bfffd 100644
--- a/src/netcf.h
+++ b/src/netcf.h
@@ -24,10 +24,6 @@
#define NETCF_H_
/*
- * FIXME: We need a way to distinguish between 'active' interfaces (i.e.,
- * ones that are up) and ones that are merely defined; maybe punt that to
- * clients ?
- *
* FIXME: NM needs a way to be notified of changes to the underlying
* network files, either we provide a way to register callbacks for an
* interface, or we hand out a list of files that contain the configs for
@@ -53,6 +49,18 @@ typedef enum {
NETCF_EEXEC /* external program execution failed or returned non-0 */
} netcf_errcode_t;
+
+/*
+ * flags accepted by ncf_num_of_interfaces and ncf_list_interfaces.
+ * IMPORTANT NOTE: These are bits, so you should assign only powers of two
+ * (Default behavior is to match NO interfaces)
+ */
+typedef enum {
+ NETCF_IFACE_INACTIVE = 1, /* match down interfaces */
+ NETCF_IFACE_ACTIVE = 2, /* match up interfaces */
+} netcf_if_flag_t;
+
+
/*
* Initialize netcf. This function must be called before any other netcf
* function can be called.
@@ -70,9 +78,10 @@ void ncf_close(struct netcf *);
* identified by their name.
*/
int
-ncf_num_of_interfaces(struct netcf *);
+ncf_num_of_interfaces(struct netcf *, unsigned int flags);
int
-ncf_list_interfaces(struct netcf *, int maxnames, char **names);
+ncf_list_interfaces(struct netcf *, int maxnames, char **names, unsigned int flags);
+
/* Look up interfaces by UUID, name and hwaddr (MAC-48) */
struct netcf_if *
diff --git a/tests/test-initscripts.c b/tests/test-initscripts.c
index 3f0545e..abaee9b 100644
--- a/tests/test-initscripts.c
+++ b/tests/test-initscripts.c
@@ -182,11 +182,11 @@ static void testListInterfaces(CuTest *tc) {
static const char *const exp_names[] = { "br0", "bond0", "lo" };
static const int exp_nint = ARRAY_CARDINALITY(exp_names);
- nint = ncf_num_of_interfaces(ncf);
+ nint = ncf_num_of_interfaces(ncf, NETCF_IFACE_ACTIVE|NETCF_IFACE_INACTIVE);
CuAssertIntEquals(tc, exp_nint, nint);
if (ALLOC_N(names, nint) < 0)
die("allocation failed");
- nint = ncf_list_interfaces(ncf, nint, names);
+ nint = ncf_list_interfaces(ncf, nint, names, NETCF_IFACE_ACTIVE|NETCF_IFACE_INACTIVE);
CuAssertIntEquals(tc, exp_nint, nint);
for (int i=0; i < exp_nint; i++) {
int found = 0;
--
1.6.0.6
14 years, 10 months
Support for VLAN interfaces
by David Lutterkort
These patches add support for VLAN interfaces, both toplevel and enslaved
to a bridge.
As previously discussed, VLAN interfaces only reference the underlying
device, so that a brde br0 with a VLAN interface eth0.42 enslaved looks
like
<interface type="bridge" startmode="onboot">
<name>br0</name>
<protocol family="ipv4">
<dhcp/>
</protocol>
<bridge stp="off">
<interface type="vlan" device="eth0" vlan="42"/>
</bridge>
</interface>
Differing from other types of interfaces, the <name/> subtag is optional
for VLAN's since it can be derived from the name of the underlying device
and the VLAN tag.
David
14 years, 10 months
[PATCH] Add active/inactive flag to ncf_num_of_interfaces() & ncf_list_interfaces().
by Laine Stump
This patch modifies ncf_num_of_interfaces() and ncf_list_interfaces to take
a flag argument that specifies whether to count/list interfaces that are
up, down, or both. It uses the SIOCGIFFLAGS ioctl to retrieve this
information.
---
src/drv_initscripts.c | 101 ++++++++++++++++++++++++++++++++++++++--------
src/internal.h | 4 +-
src/ncftool.c | 16 ++++++-
src/netcf.c | 8 ++--
src/netcf.h | 21 +++++++---
tests/test-initscripts.c | 4 +-
6 files changed, 121 insertions(+), 33 deletions(-)
diff --git a/src/drv_initscripts.c b/src/drv_initscripts.c
index fe57a52..fe74df9 100644
--- a/src/drv_initscripts.c
+++ b/src/drv_initscripts.c
@@ -30,6 +30,11 @@
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+
#include "safe-alloc.h"
#include "ref.h"
#include "list.h"
@@ -86,6 +91,7 @@ struct driver {
xsltStylesheetPtr put;
xsltStylesheetPtr get;
xmlRelaxNGPtr rng;
+ int ioctl_fd;
};
/* Entries in a ifcfg file that tell us that the interface
@@ -214,6 +220,18 @@ static int is_slave(struct netcf *ncf, const char *intf) {
return 0;
}
+static int is_active(struct netcf *ncf, const char *intf) {
+ struct ifreq ifr;
+
+ MEMZERO(&ifr, 1);
+ strncpy(ifr.ifr_name, intf, sizeof(ifr.ifr_name));
+ ifr.ifr_name[sizeof(ifr.ifr_name)] = '\0';
+ if (ioctl(ncf->driver->ioctl_fd, SIOCGIFFLAGS, &ifr)) {
+ return 0;
+ }
+ return ((ifr.ifr_flags & IFF_UP) == IFF_UP);
+}
+
static int list_interfaces(struct netcf *ncf, char ***intf) {
int nint = 0, result = 0;
struct augeas *aug = NULL;
@@ -422,11 +440,35 @@ static char *xml_prop(xmlNodePtr node, const char *name) {
return (char *) xmlGetProp(node, BAD_CAST name);
}
+static int init_ioctl_fd(struct netcf *ncf) {
+
+ int ioctl_fd;
+ int flags;
+
+ ioctl_fd = socket(AF_INET, SOCK_STREAM, 0);
+ ERR_THROW(ioctl_fd < 0, ncf, EINTERNAL, "failed to open socket for interface ioctl");
+
+ flags = fcntl(ioctl_fd, F_GETFD);
+ ERR_THROW(flags < 0, ncf, EINTERNAL, "failed to get flags for ioctl socket");
+
+ flags = fcntl(ioctl_fd, F_SETFD, flags | FD_CLOEXEC);
+ ERR_THROW(flags < 0, ncf, EINTERNAL, "failed to set FD_CLOEXEC flag on ioctl socket");
+ return ioctl_fd;
+
+error:
+ if (ioctl_fd >= 0)
+ close(ioctl_fd);
+ return -1;
+}
+
int drv_init(struct netcf *ncf) {
int r;
if (ALLOC(ncf->driver) < 0)
return -1;
+
+ ncf->driver->ioctl_fd = -1;
+
// FIXME: Check for errors
xsltInit();
r = xslt_ext_register();
@@ -436,7 +478,13 @@ int drv_init(struct netcf *ncf) {
ncf->driver->rng = rng_parse(ncf, "interface.rng");
/* We undconditionally bridge physdevs; could be more discriminating */
bridge_physdevs(ncf);
+
+ /* open a socket for interface ioctls */
+ ncf->driver->ioctl_fd = init_ioctl_fd(ncf);
+ if (ncf->driver->ioctl_fd < 0)
+ goto error;
return 0;
+
error:
FREE(ncf->driver);
return -1;
@@ -447,49 +495,68 @@ void drv_close(struct netcf *ncf) {
xsltFreeStylesheet(ncf->driver->put);
xslt_ext_unregister();
xsltCleanupGlobals();
+ if (ncf->driver->ioctl_fd >= 0)
+ close(ncf->driver->ioctl_fd);
FREE(ncf->driver);
}
-int drv_num_of_interfaces(struct netcf *ncf) {
- int nint = 0;
- char **intf = NULL;
-
- nint = list_interfaces(ncf, &intf);
- free_matches(nint, &intf);
- return nint;
-}
-
static int list_interface_ids(struct netcf *ncf,
int maxnames, char **names,
+ unsigned int flags,
const char *id_attr) {
struct augeas *aug = NULL;
- int nint = 0, nmatches = 0, result = 0, r;
+ int nint = 0, nmatches = 0, nqualified = 0, result = 0, r;
char **intf = NULL, **matches = NULL;
aug = get_augeas(ncf);
ERR_BAIL(ncf);
nint = list_interfaces(ncf, &intf);
- for (result = 0; result < nint && result < maxnames; result++) {
+ if (!names) {
+ maxnames = nint; /* if not returning list, ignore maxnames too */
+ }
+ for (result = 0; (result < nint) && (nqualified < maxnames); result++) {
nmatches = aug_submatch(ncf, intf[result], id_attr, &matches);
if (nmatches > 0) {
const char *name;
+ int is_qualified = ((flags & (NETCF_ACTIVE|NETCF_INACTIVE))
+ == (NETCF_ACTIVE|NETCF_INACTIVE));
+
r = aug_get(aug, matches[nmatches-1], &name);
ERR_COND_BAIL(r < 0, ncf, EOTHER);
- names[result] = strdup(name);
- ERR_COND_BAIL(names[result] == NULL, ncf, ENOMEM);
+
+ if (!is_qualified) {
+ int if_is_active = is_active(ncf, name);
+ if ((if_is_active && (flags & NETCF_ACTIVE))
+ || ((!if_is_active) && (flags & NETCF_INACTIVE))) {
+
+ is_qualified = 1;
+ }
+ }
+
+ if (is_qualified) {
+ if (names) {
+ names[nqualified] = strdup(name);
+ ERR_COND_BAIL(names[nqualified] == NULL, ncf, ENOMEM);
+ }
+ nqualified++;
+ }
}
free_matches(nmatches, &matches);
}
free_matches(nint, &intf);
- return result;
+ return nqualified;
error:
free_matches(nmatches, &matches);
free_matches(nint, &intf);
return -1;
}
-int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names) {
- return list_interface_ids(ncf, maxnames, names, "DEVICE");
+int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names, unsigned int flags) {
+ return list_interface_ids(ncf, maxnames, names, flags, "DEVICE");
+}
+
+int drv_num_of_interfaces(struct netcf *ncf, unsigned int flags) {
+ return list_interface_ids(ncf, 0, NULL, flags, "DEVICE");
}
static struct netcf_if *make_netcf_if(struct netcf *ncf, char *name) {
@@ -912,7 +979,7 @@ int drv_lookup_by_mac_string(struct netcf *ncf, const char *mac,
struct augeas *aug = NULL;
char *path = NULL, *ifcfg = NULL;
const char **names = NULL;
- int nmatches;
+ int nmatches = 0;
char **matches = NULL;
int r;
int result = -1;
diff --git a/src/internal.h b/src/internal.h
index 60c5855..f0ab030 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -152,8 +152,8 @@ void vreport_error(struct netcf *ncf, netcf_errcode_t errcode,
*/
int drv_init(struct netcf *netcf);
void drv_close(struct netcf *netcf);
-int drv_num_of_interfaces(struct netcf *ncf);
-int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names);
+int drv_num_of_interfaces(struct netcf *ncf, unsigned int flags);
+int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names, unsigned int flags);
struct netcf_if *drv_lookup_by_name(struct netcf *ncf, const char *name);
int drv_lookup_by_mac_string(struct netcf *, const char *mac,
int maxifaces, struct netcf_if **ifaces);
diff --git a/src/ncftool.c b/src/ncftool.c
index cee1fce..bb4c431 100644
--- a/src/ncftool.c
+++ b/src/ncftool.c
@@ -137,13 +137,21 @@ static const char *arg_value(const struct command *cmd, const char *name) {
static int cmd_list(ATTRIBUTE_UNUSED const struct command *cmd) {
int nint;
char **intf;
+ unsigned int flags = NETCF_ACTIVE;
- nint = ncf_num_of_interfaces(ncf);
+ if (opt_present(cmd, "inactive")) {
+ flags = NETCF_INACTIVE;
+ }
+ if (opt_present(cmd, "all")) {
+ flags = NETCF_ACTIVE | NETCF_INACTIVE;
+ }
+
+ nint = ncf_num_of_interfaces(ncf, flags);
if (nint < 0)
return CMD_RES_ERR;
if (ALLOC_N(intf, nint) < 0)
return CMD_RES_ENOMEM;
- nint = ncf_list_interfaces(ncf, nint, intf);
+ nint = ncf_list_interfaces(ncf, nint, intf, flags);
if (nint < 0)
return CMD_RES_ERR;
for (int i=0; i < nint; i++) {
@@ -175,6 +183,10 @@ static int cmd_list(ATTRIBUTE_UNUSED const struct command *cmd) {
static const struct command_opt_def cmd_list_opts[] = {
{ .tag = CMD_OPT_BOOL, .name = "macs",
.help = "show MAC addresses" },
+ { .tag = CMD_OPT_BOOL, .name = "all",
+ .help = "show all (up & down) interfaces" },
+ { .tag = CMD_OPT_BOOL, .name = "inactive",
+ .help = "show only inactive (down) interfaces" },
CMD_OPT_DEF_LAST
};
diff --git a/src/netcf.c b/src/netcf.c
index 4d9943c..906db7d 100644
--- a/src/netcf.c
+++ b/src/netcf.c
@@ -102,17 +102,17 @@ void ncf_close(struct netcf *ncf) {
*
* Maybe we should just list them as STRUCT NETCF_IF *
*/
-int ncf_num_of_interfaces(struct netcf *ncf) {
+int ncf_num_of_interfaces(struct netcf *ncf, unsigned int flags) {
ERR_RESET(ncf);
- return drv_num_of_interfaces(ncf);
+ return drv_num_of_interfaces(ncf, flags);
}
-int ncf_list_interfaces(struct netcf *ncf, int maxnames, char **names) {
+int ncf_list_interfaces(struct netcf *ncf, int maxnames, char **names, unsigned int flags) {
int result;
ERR_RESET(ncf);
MEMZERO(names, maxnames);
- result = drv_list_interfaces(ncf, maxnames, names);
+ result = drv_list_interfaces(ncf, maxnames, names, flags);
if (result < 0)
for (int i=0; i < maxnames; i++)
FREE(names[i]);
diff --git a/src/netcf.h b/src/netcf.h
index e209fc1..273ffdd 100644
--- a/src/netcf.h
+++ b/src/netcf.h
@@ -24,10 +24,6 @@
#define NETCF_H_
/*
- * FIXME: We need a way to distinguish between 'active' interfaces (i.e.,
- * ones that are up) and ones that are merely defined; maybe punt that to
- * clients ?
- *
* FIXME: NM needs a way to be notified of changes to the underlying
* network files, either we provide a way to register callbacks for an
* interface, or we hand out a list of files that contain the configs for
@@ -53,6 +49,18 @@ typedef enum {
NETCF_EEXEC /* external program execution failed or returned non-0 */
} netcf_errcode_t;
+
+/*
+ * flags accepted by ncf_num_of_interfaces and ncf_list_interfaces.
+ * IMPORTANT NOTE: These are bits, so you should assign only powers of two
+ * (Default behavior is to match NO interfaces)
+ */
+typedef enum {
+ NETCF_INACTIVE = 1, /* match down interfaces */
+ NETCF_ACTIVE = 2, /* match up interfaces */
+} netcf_if_flag_t;
+
+
/*
* Initialize netcf. This function must be called before any other netcf
* function can be called.
@@ -70,9 +78,10 @@ void ncf_close(struct netcf *);
* identified by their name.
*/
int
-ncf_num_of_interfaces(struct netcf *);
+ncf_num_of_interfaces(struct netcf *, unsigned int flags);
int
-ncf_list_interfaces(struct netcf *, int maxnames, char **names);
+ncf_list_interfaces(struct netcf *, int maxnames, char **names, unsigned int flags);
+
/* Look up interfaces by UUID, name and hwaddr (MAC-48) */
struct netcf_if *
diff --git a/tests/test-initscripts.c b/tests/test-initscripts.c
index 46c5920..5cca298 100644
--- a/tests/test-initscripts.c
+++ b/tests/test-initscripts.c
@@ -169,11 +169,11 @@ static void testListInterfaces(CuTest *tc) {
static const char *const exp_names[] = { "br0", "bond0", "lo" };
static const int exp_nint = ARRAY_CARDINALITY(exp_names);
- nint = ncf_num_of_interfaces(ncf);
+ nint = ncf_num_of_interfaces(ncf, NETCF_FLAG_ACTIVE|NETCF_FLAG_INACTIVE);
CuAssertIntEquals(tc, exp_nint, nint);
if (ALLOC_N(names, nint) < 0)
die("allocation failed");
- nint = ncf_list_interfaces(ncf, nint, names);
+ nint = ncf_list_interfaces(ncf, nint, names, NETCF_FLAG_ACTIVE|NETCF_FLAG_INACTIVE);
CuAssertIntEquals(tc, exp_nint, nint);
for (int i=0; i < exp_nint; i++) {
int found = 0;
--
1.6.0.6
14 years, 10 months
libaugeas CFLAGS variable
by Jonas Eriksson
Hi,
During development I discovered that the LIBAUGEAS_CFLAGS
variable is not honoured in src/Makefile(.am). This patch adds
$LIBAUGEAS_CFLAGS to Makefile.am.
(The driver is ready for a first mailing list post Real Soon
Now(tm), I just want to test it a bit more first)
Regards,
Jonas
--
Jonas Eriksson
Consultant at AS/EAB/FLJ/IL
Combitech AB
Älvsjö, Sweden
14 years, 10 months
SuSE driver
by Jonas Eriksson
The things I have tried worked. I have a few problems, though:
' and " are not handeled. As bridges SuSE have their own
ifcfg-file, the BRIDGE_PORT contain the interfaces used in that
bridge, separated by whitespaces. My problem is mostly whether to
extend shellvars.aug to handle ' and ", or if this should be
handled in C/XSLT.
In SLE10, interfaces could be named after their mac address using
eth-id-<mac>. This is now defunct and handled by udev-rules, but
I have somewhat retained handling of this, but convert it to
ethX-syntax. However, when facing an interface-element in
netcf-xml with a mac address, I convert this to a
eth-id-interface in XSLT, and then to ethX in C by looking up the
mac. Instead of doing this, the driver should retain the original
ethX-name as an fallback in case the mac is not found.
Whenever using define in netcf, i get:
error: unspecified error
error: aug_save failed
After doing some dry runs with augtool, I have concluded that
this is most probably due to augeas trying to save the
address-files in /sys. Is this a problem when using
the initscript-driver as well?
Currently, there is a mix between functions that accept name or
path. I am planning to clean up this mess, preferably
standardizing on name as argument.
I also have a few questions/opinions:
Should we include some general debug macros? I stole the ones
from libvirt and removed them before this post, and i had alot of
use for them, for example to see the <forest>-xml when doing a
define.
Alot of code are the same between the initscript driver, and
probably will be for other drivers as well. I recommend that this
code is broken out, for example to a Linux-helper? The same goes for
both C-code (e.g. handling of mac-address lookups) and XSLT (e.g.
bonding-options).
I changed the augeas save-behaviour to "backup" in the augeas
init function (which probably also could be lifted out to a
general helper file). I left it in there, since I like it alot,
but we should probably discuss it further.
Regards,
Jonas
--
Jonas Eriksson
Consultant at AS/EAB/FLJ/IL
Combitech AB
Älvsjö, Sweden
14 years, 10 months
Multiple interfaces with identical mac-addresses
by Jonas Eriksson
Hi,
Looking through the driver API, I came across the
drv_lookup_by_mac_string. This function is prototyped in
internal.h, so I assume that it is a part of the public driver
API.
However, a problem may arise when multiple top-level interfaces
share mac addresses, as drv_lookup_by_mac_string only may return
one struct netcf_if *. This can occurr when using vlan
interfaces, e.g. eth0.2 and eth0.3, or if vlan ifs are not to be
considered top-level interfaces, the bridges or bonds that these
interfaces are a part of. I therefore recommend a switch to a
drv_list_interfaces-prototype for drv_lookup_by_mac_string.
For reference:
int drv_list_interfaces(struct netcf *ncf, int maxnames, char **names);
Best regards,
Jonas Eriksson
--
Jonas Eriksson
Consultant at AS/EAB/FLJ/IL
Combitech AB
Älvsjö, Sweden
14 years, 10 months
[RFC] Reporting host interface status/statistics via netcf/libvirt, and listing active vs. inactive interfaces
by Laine Stump
I've already been working on incorporating physical host interface
configuration into libvirt by way of using libnetcf on the backend. It's
becoming apparent that, in addition to modifying and reporting the
current configuration of interfaces, libvirt users also want to query
current status of each interface (up/down, possibly other flags,
packet/byte/error counts, current IP address, etc).
There are two possible ways of doing this:
1) maintain libnetcf's focus on just interface configuration, and
add code directly into libvirt to grab this information via
appropriate ioctls
or
2) add the functionality to libnetcf, and have libvirt call the
new libnetcf API.
(2) seems to make the most sense, because likely other libnetcf
consumers will want this capability too.
I'm thinking of a single API, something like:
int netcf_if_status(netcf_if *, netcf_if_stats *);
(or maybe int netcf_if_info(netcf_if *, netcf_if_info *))
I haven't really put much thought into the details of what should be in
netcf_if_stats yet (beyond what I listed above), but wanted to get this
idea out there so people can start sounding off (if I'm going down the
wrong road, I'd rather be put on the right path before I get too far along!)
This function could be exposed in the libvirt API as something like:
int virInterfaceStatus|Info(virInterffacePtr iface,
virInterfaceStats|Info *info);
Any comments/ideas on this?
(One possible complication I can see is interfaces with multiple
associated IPs. On some platforms, each interface can have only a single
IPv4 and a single IPv6 address (more IPs == more interfaces), but on
others there can be multiples.)
A (kind of) separate issue: In libvirt we want to be able to list active
(up) and inactive (down) interfaces separately. For consistency,
libvirt's way of exposing that will be to mimic what is done with
virConnectListNetworks() (active) vs. virConnectListDefinedNetworks()
(inactive).
But netcf could do it with an extra argument to ncf_list_interfaces().
If the latter, should the default behavior be to list all interfaces,
with flags set to eliminate up or down interfaces?
0 (list all)
NETCF_NOLIST_UP
NETCF_NOLIST_DOWN
Or should the values be something like this:
0 (list all)
NETCF_LIST_UP_ONLY
NETCF_LIST_DOWN_ONLY
(UP_ONLY + DOWN_ONLY would be equivalent to 0. As long as nobody came up
with a good reason for "0".
So should we do one of those, or should we mimic libirt's virNetwork API
in libnetcf too?
14 years, 10 months