<?xml version="1.0"?>
<!-- A Relax NG schema for network interfaces -->
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
         xmlns:v="http://netcf.org/xml/version/1.0"
         datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
  <!-- Versions for this schema are simple integers that are incremented
       every time a changed (but backwards compatible) version
       is released. The current version is indicated with the v:serial
       attribute on the start element.
  -->
  <start v:serial="4">
    <choice>
      <ref name="ethernet-interface"/>
      <ref name="bridge-interface"/>
      <ref name="bond-interface"/>
      <ref name="vlan-interface"/>
    </choice>
  </start>

  <include href="basictypes.rng"/>
  <!--
       FIXME: How do we handle VLAN's ? Should they be their own interface
       or should we treat them as an option on the base interface ?  For
       example, for vlan eth0.42, it would make sense to make that part of
       the definition of the eth0 interface.
  -->

  <!--
       Ethernet adapter
  -->
  <define name="basic-ethernet-content">
    <interleave>
      <attribute name="type">
        <value>ethernet</value>
      </attribute>
      <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 ? -->
      <optional>
        <element name="mac">
          <attribute name="address"><ref name="macAddr"/></attribute>
        </element>
      </optional>
      <ref name="link-speed-state"/>
      <!-- FIXME: Allow (some) ethtool options -->
    </interleave>
  </define>

  <!-- Ethernet adapter without IP addressing, e.g. for a bridge -->
  <define name="bare-ethernet-interface">
    <element name="interface">
      <interleave>
        <ref name="basic-ethernet-content"/>
      </interleave>
    </element>
  </define>

  <define name="ethernet-interface">
    <element name="interface">
      <interleave>
        <ref name="startmode"/>
        <ref name="basic-ethernet-content"/>
        <ref name="mtu"/>
        <ref name="interface-addressing"/>
      </interleave>
    </element>
  </define>

  <!--
      VLAN's
  -->
  <define name="vlan-interface-common">
    <attribute name="type">
      <value>vlan</value>
    </attribute>
    <!-- The name attribute is only useful for reporting back and is always
         of the form DEVICE.VLAN
    -->
    <optional><ref name="name-attr"/></optional>
    <ref name="link-speed-state"/>
  </define>

  <define name="vlan-device">
    <element name="vlan">
      <attribute name="tag"><ref name="vlan-id"/></attribute>
      <element name="interface">
        <attribute name="name"><ref name="deviceName"/></attribute>
      </element>
    </element>
  </define>

  <define name="bare-vlan-interface">
    <element name="interface">
      <interleave>
        <ref name="vlan-interface-common"/>
        <ref name="vlan-device"/>
      </interleave>
    </element>
  </define>

  <define name="vlan-interface">
    <element name="interface">
      <interleave>
        <ref name="vlan-interface-common"/>
        <ref name="startmode"/>
        <ref name="mtu"/>
        <ref name="interface-addressing"/>
        <ref name="vlan-device"/>
      </interleave>
    </element>
  </define>

  <!--
       Bridges
  -->
  <define name="bridge-interface">
    <element name="interface">
      <interleave>
        <attribute name="type">
          <value>bridge</value>
        </attribute>
        <ref name="name-attr"/>
        <ref name="startmode"/>
        <ref name="mtu"/>
        <ref name="interface-addressing"/>
        <element name="bridge">
          <optional>
            <attribute name="stp">
              <ref name="virOnOff"/>
            </attribute>
          </optional>
          <!-- Bridge forward delay
               (see "ip link set <dev> type bridge forward_delay") -->
          <optional v:since="2">
            <attribute name="delay"><ref name="timeval"/></attribute>
          </optional>
          <zeroOrMore>
            <choice>
              <ref name="bare-ethernet-interface"/>
              <ref name="bare-vlan-interface"/>
              <ref v:since="2" name="bare-bond-interface"/>
            </choice>
          </zeroOrMore>
        </element>
      </interleave>
    </element>
  </define>
  <!-- Jim Fehlig would like support for other bridge attributes, in
       particular hellotime, forwarddelay, and maxage
  -->

  <!--
      Bonds
  -->
  <define name="bond-interface-common">
    <attribute name="type">
      <value>bond</value>
    </attribute>
    <ref name="name-attr"/>
    <ref name="link-speed-state"/>
  </define>

  <define name="bond-element">
    <element name="bond">
      <optional>
        <attribute name="mode">
          <choice>
            <value>balance-rr</value>
            <!-- The primary interface is the first interface child
                 of the bond element -->
            <value>active-backup</value>
            <value>balance-xor</value>
            <value>broadcast</value>
            <value>802.3ad</value>
            <value>balance-tlb</value>
            <value>balance-alb</value>
          </choice>
        </attribute>
      </optional>

      <!-- FIXME: add more attributes

           mode == 802.3ad
             ad_select
             lacp_rate
             xmit_hash_policy

           mode == active-backup
             fail_over_mac
             num_grat_arp when mode == active-backup (since 3.3.0)
             num_unsol_na when mode == active-backup (ipv6, since 3.4.0)

           mode == balance-xor
             xmit_hash_policy       (since 2.6.3/3.2.2)
      -->

      <interleave>
        <optional>
          <choice>
            <element name="miimon">
              <!-- miimon frequency in ms -->
              <attribute name="freq"><ref name="unsignedInt"/></attribute>
              <optional>
                <attribute name="downdelay"><ref name="unsignedInt"/></attribute>
              </optional>
              <optional>
                <attribute name="updelay"><ref name="unsignedInt"/></attribute>
              </optional>
              <optional>
                <!-- use_carrier -->
                <attribute name="carrier">
                  <choice>
                    <!-- use MII/ETHTOOL ioctl -->
                    <value>ioctl</value>
                    <!-- use netif_carrier_ok() -->
                    <value>netif</value>
                  </choice>
                </attribute>
              </optional>
            </element>
            <element name="arpmon">
              <attribute name="interval"><ref name="unsignedInt"/></attribute>
              <attribute name="target"><ref name="ipv4Addr"/></attribute>
              <optional>
                <attribute name="validate">
                  <choice>
                    <value>none</value>
                    <value>active</value>
                    <value>backup</value>
                    <value>all</value>
                  </choice>
                </attribute>
              </optional>
            </element>
          </choice>
        </optional>

        <oneOrMore>
          <!-- The slave interfaces -->
          <ref name="bare-ethernet-interface"/>
        </oneOrMore>
      </interleave>
    </element>
  </define>

  <define name="bare-bond-interface">
    <element name="interface">
      <interleave>
        <ref name="bond-interface-common"/>
        <ref name="bond-element"/>
      </interleave>
    </element>
  </define>

  <define name="bond-interface">
    <element name="interface">
      <interleave>
        <ref name="bond-interface-common"/>
        <ref name="startmode"/>
        <ref name="mtu"/>
        <ref name="interface-addressing"/>
        <ref name="bond-element"/>
      </interleave>
    </element>
  </define>

  <!-- Basic attributes for all interface types -->
  <define name="name-attr">
    <!-- The device name, like eth0 or br2 -->
    <attribute name="name"><ref name="deviceName"/></attribute>
  </define>

  <define name="mtu">
    <optional>
      <element name="mtu">
        <attribute name="size"><ref name="unsignedInt"/></attribute>
      </element>
    </optional>
  </define>

  <define name="startmode">
    <optional>
      <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>
    </optional>
  </define>

  <!--
       Assignment of addresses to an interface, allowing for
       different protocols
  -->
  <define name="interface-addressing">
    <choice>
      <group>
        <optional>
          <ref name="protocol-ipv4"/>
        </optional>
        <optional v:since="3">
          <ref name="protocol-ipv6"/>
        </optional>
      </group>
      <group>
        <optional v:since="3">
          <ref name="protocol-ipv6"/>
        </optional>
        <optional>
          <ref name="protocol-ipv4"/>
        </optional>
      </group>
    </choice>
  </define>

  <define name="protocol-ipv4">
    <element name="protocol">
      <attribute name="family">
        <value>ipv4</value>
      </attribute>
      <interleave>
        <optional>
          <ref name="dhcp-element"/>
        </optional>
        <zeroOrMore>
          <element name="ip">
            <attribute name="address"><ref name="ipv4Addr"/></attribute>
            <optional>
              <attribute name="prefix"><ref name="ipv4Prefix"/></attribute>
            </optional>
          </element>
        </zeroOrMore>
        <optional>
          <element name="route">
            <attribute name="gateway"><ref name="ipv4Addr"/></attribute>
          </element>
        </optional>
      </interleave>
    </element>
  </define>

  <define name="protocol-ipv6">
    <element name="protocol">
      <attribute name="family">
        <value>ipv6</value>
      </attribute>
      <interleave>
        <optional>
          <element name="autoconf"><empty/></element>
        </optional>
        <optional>
          <ref name="dhcp-element"/>
        </optional>
        <zeroOrMore>
          <element name="ip">
            <attribute name="address"><ref name="ipv6Addr"/></attribute>
            <optional>
              <attribute name="prefix"><ref name="ipv6Prefix"/></attribute>
            </optional>
          </element>
        </zeroOrMore>
        <optional>
          <element name="route">
            <attribute name="gateway"><ref name="ipv6Addr"/></attribute>
          </element>
        </optional>
      </interleave>
    </element>
  </define>

  <define name="dhcp-element">
    <element name="dhcp">
      <optional>
        <attribute name="peerdns">
          <ref name="virYesNo"/>
        </attribute>
      </optional>
    </element>
  </define>

  <!-- Jim Fehlig (<jfehlig@novell.com>) suggest the
       following additions to DHCP:

       WRT dhcp element, would it make sense to consider hostname (hostname
       to send to server) and if to change the local hostname to the
       hostname delivered via dhcp?  E.g.  hostname="foo" (default
       `hostname`) sethostname

       Also route:
         setrouting (default "yes")
         setdefaultroute (default "yes")

       and NIS:
         nis (default "yes")
         setnisdomain (default "yes")

       What about dhcpv6?  A separate <dhcp6 /> element?
  -->

  <!-- Jim Fehlig suggest adding static routing info

       As for routing info, how about a separate route element:

       <route gateway="192.168.0.1" /> # destination=default
       <route destination="default" gateway="192.168.0.1" />
       <route destination="10.0.0.0/8" gateway="192.168.0.2" />
       <route destination="2001:DB8:C::/64" gateway="2001:DB8:C::1" />
       <route destination="2001:DB8::/32"> # unrecheable route (loopback)

       It would perhaps make sense to use iproute2 names, that is prefix
       instead of destination and nexthop instead of gateway.
  -->

  <!-- Type library -->

  <define name="timeval">
    <data type="double">
      <param name="minInclusive">0</param>
    </data>
  </define>

  <define name="vlan-id">
    <data type="unsignedInt">
      <param name="maxInclusive">4095</param>
    </data>
  </define>
</grammar>
