<!-- A Relax NG schema for network interfaces -->
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
         datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
  <start>
    <choice>
      <ref name="ethernet-interface"/>
      <ref name="bridge-interface"/>
      <ref name="bond-interface"/>
      <ref name="vlan-interface"/>
    </choice>
  </start>

  <!--
       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">
    <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="mac-addr"/></attribute>
      </element>
    </optional>
    <!-- FIXME: Allow (some) ethtool options -->
  </define>

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

  <define name="ethernet-interface">
    <element name="interface">
      <ref name="startmode"/>
      <ref name="basic-ethernet-content"/>
      <ref name="mtu"/>
      <ref name="interface-addressing"/>
    </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>
  </define>

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

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

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

  <!--
       Bridges
  -->
  <define name="bridge-interface">
    <element name="interface">
      <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="on-or-off"/>
          </attribute>
        </optional>
        <oneOrMore>
          <choice>
            <ref name="bare-ethernet-interface"/>
            <ref name="bare-vlan-interface"/>
          </choice>
        </oneOrMore>
      </element>
    </element>
  </define>
  <!-- Jim Fehlig would like support for other bridge attributes, in
       particular hellotime, forwarddelay, and maxage
  -->

  <!--
      Bonds
  -->
  <define name="bond-interface">
    <element name="interface">
      <attribute name="type">
        <value>bond</value>
      </attribute>
      <ref name="name-attr"/>
      <ref name="startmode"/>
      <ref name="mtu"/>
      <ref name="interface-addressing"/>
      <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)
        -->

        <choice>
          <element name="miimon">
            <!-- miimon frequency in ms -->
            <attribute name="freq"><ref name="uint"/></attribute>
            <optional>
              <attribute name="downdelay"><ref name="uint"/></attribute>
            </optional>
            <optional>
              <attribute name="updelay"><ref name="uint"/></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="uint"/></attribute>
            <attribute name="target"><ref name="ipv4-addr"/></attribute>
            <optional>
              <attribute name="validate">
                <choice>
                  <value>none</value>
                  <value>active</value>
                  <value>backup</value>
                  <value>all</value>
                </choice>
              </attribute>
            </optional>
          </element>
        </choice>
        <oneOrMore>
          <!-- The slave interfaces -->
          <ref name="bare-ethernet-interface"/>
        </oneOrMore>
      </element>
    </element>
  </define>

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

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

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

  <!--
       Assignment of addresses to an interface, allowing for
       different protocols
  -->
  <define name="interface-addressing">
    <optional>
      <element name="protocol">
        <ref name="protocol-ipv4"/>
      </element>
    </optional>
  </define>

  <define name="protocol-ipv4">
    <attribute name="family">
      <value>ipv4</value>
    </attribute>
    <choice>
      <element name="dhcp">
        <optional>
          <attribute name="peerdns">
            <ref name="yes-or-no"/>
          </attribute>
        </optional>
      </element>
      <!-- FIXME: This format should be good enough for IPv4 and IPv6, i.e.

           ipaddr="192.168.0.5/24"
           ipaddr="2001:DB8:ABCD::1/64"

           but will cause some backend pain
      -->
      <group>
        <element name="ip">
          <attribute name="address"><ref name="ipv4-addr"/></attribute>
          <optional>
            <attribute name="prefix"><ref name="ipv4-prefix"/></attribute>
          </optional>
        </element>
        <optional>
          <element name="route">
            <attribute name="gateway"><ref name="ipv4-addr"/></attribute>
          </element>
        </optional>
      </group>
    </choice>
  </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.
  -->

  <!-- Auxiliary definitions -->
  <define name="on-or-off">
    <choice>
      <value>on</value>
      <value>off</value>
    </choice>
  </define>

  <define name="yes-or-no">
    <choice>
      <value>yes</value>
      <value>no</value>
    </choice>
  </define>

  <!-- Type library -->

  <define name='uint'>
    <data type='unsignedInt'>
      <param name="pattern">[0-9]+</param>
    </data>
  </define>

  <define name='device-name'>
    <data type='string'>
      <param name="pattern">[a-zA-Z0-9_\.\-:/]+</param>
    </data>
  </define>

  <define name='UUID'>
    <choice>
      <data type='string'>
        <param name="pattern">[a-fA-F0-9]{32}</param>
      </data>
      <data type='string'>
        <param name="pattern">[a-fA-F0-9]{8}\-([a-fA-F0-9]{4}\-){3}[a-fA-F0-9]{12}</param>
      </data>
    </choice>
  </define>

  <define name='mac-addr'>
    <data type='string'>
      <param name="pattern">([a-fA-F0-9]{2}:){5}[a-fA-F0-9]{2}</param>
    </data>
  </define>

  <define name='ipv4-addr'>
    <data type='string'>
      <param name="pattern">([0-2]?[0-9]?[0-9]\.){3}[0-2]?[0-9]?[0-9]</param>
    </data>
  </define>

  <define name='ipv4-prefix'>
    <data type='string'>
      <param name="pattern">[1-9]|[12][0-9]|3[0-2]</param>
    </data>
  </define>

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