Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package nvme-stas for openSUSE:Factory 
checked in at 2022-03-23 20:18:31
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/nvme-stas (Old)
 and      /work/SRC/openSUSE:Factory/.nvme-stas.new.25692 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "nvme-stas"

Wed Mar 23 20:18:31 2022 rev:2 rq:964187 version:1.0~rc4

Changes:
--------
--- /work/SRC/openSUSE:Factory/nvme-stas/nvme-stas.changes      2022-03-04 
00:18:46.180299506 +0100
+++ /work/SRC/openSUSE:Factory/.nvme-stas.new.25692/nvme-stas.changes   
2022-03-23 20:20:24.506531671 +0100
@@ -1,0 +2,17 @@
+Wed Mar 23 08:23:34 UTC 2022 - Daniel Wagner <[email protected]>
+
+- Update to version 1.0-rc4:
+  * Check ignore-iface when creating TransportId object
+  * Adding man pages for ip-family and ignore-iface
+  * Add ignore-iface and ip-family conf. options
+  * Update the documentation
+  * Change default address returned by name resolver
+  * Filter out invalid IP addresses. (bsc#1197361)
+  * When reading the Host NQN, warn people if the NQN seems invalid
+  * Print descriptive message when unable to run stafctl/stacctl
+  * Use the newly added cntlrtype to check the type of controller
+  * minor fix to previous change to set the log level on libnvme
+  * LOG: enable libnvme debug when trace is enabled
+- Added python3-netifaces dependency
+
+-------------------------------------------------------------------

Old:
----
  nvme-stas-1.0~rc2.obscpio

New:
----
  nvme-stas-1.0~rc4.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ nvme-stas.spec ++++++
--- /var/tmp/diff_new_pack.0VCu6Z/_old  2022-03-23 20:20:25.030531968 +0100
+++ /var/tmp/diff_new_pack.0VCu6Z/_new  2022-03-23 20:20:25.034531969 +0100
@@ -17,24 +17,27 @@
 
 
 Name:           nvme-stas
-Version:        1.0~rc2
+Version:        1.0~rc4
 Release:        0
 Summary:        NVMe STorage Appliance Services
 License:        Apache-2.0
 URL:            https://github.com/linux-nvme/nvme-stas
 Source0:        nvme-stas-%{version}.tar.gz
 BuildRequires:  gobject-introspection
+BuildRequires:  libnvme-devel >= 1.0~7
 BuildRequires:  meson >= 0.52.0
 BuildRequires:  python3
 BuildRequires:  python3-dasbus
 BuildRequires:  python3-gobject
-BuildRequires:  python3-libnvme >= 1.0~4
+BuildRequires:  python3-libnvme >= 1.0~7
+BuildRequires:  python3-netifaces
 BuildRequires:  python3-pyudev
 BuildRequires:  python3-systemd
 BuildRequires:  systemd-rpm-macros
 Requires:       python3-dasbus
 Requires:       python3-gobject
-Requires:       python3-libnvme >= 1.0~4
+Requires:       python3-libnvme >= 1.0~7
+Requires:       python3-netifaces
 Requires:       python3-pyudev
 Requires:       python3-systemd
 

++++++ _service ++++++
--- /var/tmp/diff_new_pack.0VCu6Z/_old  2022-03-23 20:20:25.090532001 +0100
+++ /var/tmp/diff_new_pack.0VCu6Z/_new  2022-03-23 20:20:25.094532004 +0100
@@ -5,7 +5,7 @@
     <param name="filename">nvme-stas</param>
     <!-- <param name="versionformat">@PARENT_TAG@+@TAG_OFFSET@</param> -->
     <param name="versionformat">@PARENT_TAG@</param>
-    <param name="revision">v1.0-rc2</param>
+    <param name="revision">v1.0-rc4</param>
     <param name="match-tag">v[01].[0-9]*</param>
     <param name="versionrewrite-pattern">v([^+]*)-rc([0-9]+)</param>
     <param name="versionrewrite-replacement">\1~rc\2</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.0VCu6Z/_old  2022-03-23 20:20:25.118532017 +0100
+++ /var/tmp/diff_new_pack.0VCu6Z/_new  2022-03-23 20:20:25.126532021 +0100
@@ -1,7 +1,7 @@
 <servicedata>
   <service name="tar_scm">
     <param name="url">https://github.com/linux-nvme/nvme-stas.git</param>
-    <param 
name="changesrevision">6cd94b82f7a96d4eac2a715a13782a605a38d502</param>
+    <param 
name="changesrevision">3bb3776d81e63eed5b254d453a0cd01fa27ef581</param>
   </service>
 </servicedata>
 (No newline at EOF)

++++++ nvme-stas-1.0~rc2.obscpio -> nvme-stas-1.0~rc4.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/.github/workflows/meson-test.yml 
new/nvme-stas-1.0~rc4/.github/workflows/meson-test.yml
--- old/nvme-stas-1.0~rc2/.github/workflows/meson-test.yml      2022-02-21 
18:58:16.000000000 +0100
+++ new/nvme-stas-1.0~rc4/.github/workflows/meson-test.yml      2022-03-15 
18:30:55.000000000 +0100
@@ -15,30 +15,14 @@
       - uses: actions/checkout@v2
       - name: Install requirements
         run: |
-          sudo apt-get install -y python3-pyudev python3-systemd python3-gi 
meson
+          sudo apt-get install -y libjson-c-dev python3-pyudev python3-systemd 
python3-gi python3-netifaces meson
           python -m pip install --upgrade pip dasbus pylint pyflakes
 
-      - name: Checkout libnvme
-        uses: actions/checkout@v2
+      - uses: BSFishy/[email protected]
         with:
-          repository: linux-nvme/libnvme
-          path: libnvme
-
-      - name: Build and install libnvme
-        run: |
-          cd libnvme
-          meson .build
-          cd .build
-          ninja
-          sudo meson install
-
-      - name: Configure nvme-stas
-        run: PYTHONPATH=libnvme/.build meson .build
-
-      - name: Test
-        run: |
-          cd .build
-          PYTHONPATH=../libnvme/.build meson test -v
+          setup-options: --werror
+          options: --verbose
+          action: test
 
       - name: Upload logs
         if: failure()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/.gitignore 
new/nvme-stas-1.0~rc4/.gitignore
--- old/nvme-stas-1.0~rc2/.gitignore    2022-02-21 18:58:16.000000000 +0100
+++ new/nvme-stas-1.0~rc4/.gitignore    2022-03-15 18:30:55.000000000 +0100
@@ -1,3 +1,6 @@
 .build
 obj-x86_64-linux-gnu
 __pycache__
+
+subprojects/*
+!subprojects/*.wrap
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/DISTROS.md 
new/nvme-stas-1.0~rc4/DISTROS.md
--- old/nvme-stas-1.0~rc2/DISTROS.md    2022-02-21 18:58:16.000000000 +0100
+++ new/nvme-stas-1.0~rc4/DISTROS.md    2022-03-15 18:30:55.000000000 +0100
@@ -14,21 +14,33 @@
 
 ## Run-time dependencies
 
-nvme-stas requires Linux kernel version of 5.14 or later. This version of 
Linux introduces a new configuration parameter (`host-iface`) needed by the 
nvme-tcp kernel module.
+nvme-stas is built on top of libnvme, which is used to interact with the 
kernel's NVMe driver (i.e. `drivers/nvme/host/`). To support all the features 
of nvme-stas, several changes to the Linux kernel are required. nvme-stas can 
also operate with older kernels, but with limited functionality. Kernel 5.18 
provides all the features needed by nvme-stas. nvme-stas can also work with 
older kernels that include back-ported changes to the NVMe driver.
 
-nvme-stas also depends on the following run-time libraries and modules. Note 
that versions listed are the versions that were tested with. With the exception 
of the Linux kernel 5.14, which is the mandatory minimum kernel required, all 
other libraries could potentially work with an earlier version.
+The next table shows different features that were added to the NVMe driver and 
in which version of the Linux kernel they were added (the list of git patches 
can be found in addendum). Note that the ability to query the NVMe driver to 
determine what options it supports was added in 5.17. This is needed if 
nvme-stas is to make the right decision on whether a feature is supported. 
Otherwise, nvme-stas can only rely on the kernel version to decide what is 
supported. This can greatly limit the features supported on back-ported kernels.
+
+| Feature                                                      | Introduced in 
kernel version |
+| ------------------------------------------------------------ | 
---------------------------- |
+| **`host-iface` option** - Ability to force TCP connections over a specific 
interface. Needed for zeroconf provisioning. | 5.14                         |
+| **TP8013 Support** - Discovery Controller (DC) Unique NQN. Allow the 
creation of connections to DC with a NQN other than the default 
`nqn.2014-08.org.nvmexpress.discovery` | 5.16                         |
+| **Query supported options** - Allow user-space applications to query which 
options the NVMe driver supports | 5.17                         |
+| **TP8010 Support** - Ability for a Host to register with a Discovery 
Controller. This version of the kernel introduces a new event to indicate to 
user-space apps (e.g. nvme-stas) when a connection to a DC is restored. This is 
used to trigger a re-registration of the host. This kernel also exposes the DC 
Type (dctype) attribute through the sysfs, which is needed to determine whether 
registration is supported. | 5.18                         |
+
+nvme-stas also depends on the following run-time libraries and modules. Note 
that versions listed are the versions that were tested with. 
 
 | Library                                         | Min version | stafd        
 | stacd         |
 | ----------------------------------------------- | ----------- | 
------------- | ------------- |
 | libnvme                                         | 1.0         | 
**Mandatory** | **Mandatory** |
 | python3-dasbus                                  | 1.6         | 
**Mandatory** | **Mandatory** |
+| python3-netifaces                               | 0.10.4      | 
**Mandatory** | **Mandatory** |
 | python3-pyudev                                  | 0.22.0      | 
**Mandatory** | **Mandatory** |
 | python3-systemd                                 | 234         | 
**Mandatory** | **Mandatory** |
-| python3-gi (Debian) OR python3-gobject (Fedora) | 3.40.1      | 
**Mandatory** | **Mandatory** |
-| nvme-tcp (kernel module)                        | 5.14        | 
**Mandatory** | **Mandatory** |
-| dbus-daemon                                     | 1.12.20     | 
**Mandatory** | **Mandatory** |
+| python3-gi (Debian) OR python3-gobject (Fedora) | 3.36.0      | 
**Mandatory** | **Mandatory** |
+| nvme-tcp (kernel module)                        | 5.18 *      | 
**Mandatory** | **Mandatory** |
+| dbus-daemon                                     | 1.12.2      | 
**Mandatory** | **Mandatory** |
 | avahi-daemon                                    | 0.8         | 
**Mandatory** | Not required  |
 
+* Kernel 5.18 provides full functionality. nvme-stas can work with older 
kernels, but with limited functionality. 
+
 ## Things to do post installation
 
 ### D-Bus configuration
@@ -68,3 +80,228 @@
 ### Enabling and starting the daemons
 
 Lastly, the two daemons, `stafd` and `stacd`, should be enabled (e.g. 
`systemctl enable stafd.service stacd.service`) and started (e.g. `systemctl 
start stafd.service stacd.service`).
+
+# Addendum
+
+## Kernel patches
+
+Here's the list of kernel patches (added in kernels 5.14 to 5.18) that will 
enable all features of nvme-stas.
+
+```
+commit e3448b134426741902b6e2c07cbaf5f66cfd2ebc
+Author: Martin Belanger <[email protected]>
+Date:   Tue Feb 8 14:18:02 2022 -0500
+
+    nvme: Expose cntrltype and dctype through sysfs
+
+    TP8010 introduces the Discovery Controller Type attribute (dctype).
+    The dctype is returned in the response to the Identify command. This
+    patch exposes the dctype through the sysfs. Since the dctype depends on
+    the Controller Type (cntrltype), another attribute of the Identify
+    response, the patch also exposes the cntrltype as well. The dctype will
+    only be displayed for discovery controllers.
+
+    A note about the naming of this attribute:
+    Although TP8010 calls this attribute the Discovery Controller Type,
+    note that the dctype is now part of the response to the Identify
+    command for all controller types. I/O, Discovery, and Admin controllers
+    all share the same Identify response PDU structure. Non-discovery
+    controllers as well as pre-TP8010 discovery controllers will continue
+    to set this field to 0 (which has always been the default for reserved
+    bytes). Per TP8010, the value 0 now means "Discovery controller type is
+    not reported" instead of "Reserved". One could argue that this
+    definition is correct even for non-discovery controllers, and by
+    extension, exposing it in the sysfs for non-discovery controllers is
+    appropriate.
+
+    Signed-off-by: Martin Belanger <[email protected]>
+
+commit 68c483a105ce7107f1cf8e1ed6c2c2abb5baa551
+Author: Martin Belanger <[email protected]>
+Date:   Thu Feb 3 16:04:29 2022 -0500
+
+    nvme: send uevent on connection up
+
+    When connectivity with a controller is lost, the driver will keep
+    trying to reconnect once every 10 sec. When connection is restored,
+    user-space apps need to be informed so that they can take proper
+    action. For example, TP8010 introduces the DIM PDU, which is used to
+    register with a discovery controller (DC). The DIM PDU is sent from
+    user-space.  The DIM PDU must be sent every time a connection is
+    established with a DC. Therefore, the kernel must tell user-space apps
+    when connection is restored so that registration can happen.
+
+    The uevent sent is a "change" uevent with environmental data
+    set to: "NVME_EVENT=connected".
+
+    Signed-off-by: Martin Belanger <[email protected]>
+    Reviewed-by: Hannes Reinecke <[email protected]>
+    Reviewed-by: Sagi Grimberg <[email protected]>
+    Reviewed-by: Chaitanya Kulkarni <[email protected]>
+
+commit f18ee3d988157ebcadc9b7e5fd34811938f50223
+Author: Hannes Reinecke <[email protected]>
+Date:   Tue Dec 7 14:55:49 2021 +0100
+
+    nvme-fabrics: print out valid arguments when reading from /dev/nvme-fabrics
+
+    Currently applications have a hard time figuring out which
+    nvme-over-fabrics arguments are supported for any given kernel;
+    the ioctl will return an error code on failure, and the application
+    has to guess whether this was due to an invalid argument or due
+    to a connection or controller error.
+    With this patch applications can read a list of supported
+    arguments by simply reading from /dev/nvme-fabrics, allowing
+    them to validate the connection string.
+
+    Signed-off-by: Hannes Reinecke <[email protected]>
+    Reviewed-by: Chaitanya Kulkarni <[email protected]>
+    Signed-off-by: Christoph Hellwig <[email protected]>
+
+
+commit e5ea42faa773c6a6bb5d9e9f5c2cc808940b5a55
+Author: Hannes Reinecke <[email protected]>
+Date:   Wed Sep 22 08:35:25 2021 +0200
+
+    nvme: display correct subsystem NQN
+
+    With discovery controllers supporting unique subsystem NQNs the
+    actual subsystem NQN might be different from that one passed in
+    via the connect args. So add a helper to display the resulting
+    subsystem NQN.
+
+    Signed-off-by: Hannes Reinecke <[email protected]>
+    Reviewed-by: Chaitanya Kulkarni <[email protected]>
+    Signed-off-by: Christoph Hellwig <[email protected]>
+
+commit 20e8b689c9088027b7495ffd6f80812c11ecc872
+Author: Hannes Reinecke <[email protected]>
+Date:   Wed Sep 22 08:35:24 2021 +0200
+
+    nvme: Add connect option 'discovery'
+
+    Add a connect option 'discovery' to specify that the connection
+    should be made to a discovery controller, not a normal I/O controller.
+    With discovery controllers supporting unique subsystem NQNs we
+    cannot easily distinguish by the subsystem NQN if this should be
+    a discovery connection, but we need this information to blank out
+    options not supported by discovery controllers.
+
+    Signed-off-by: Hannes Reinecke <[email protected]>
+    Reviewed-by: Chaitanya Kulkarni <[email protected]>
+    Signed-off-by: Christoph Hellwig <[email protected]>
+
+commit 954ae16681f6bdf684f016ca626329302a38e177
+Author: Hannes Reinecke <[email protected]>
+Date:   Wed Sep 22 08:35:23 2021 +0200
+
+    nvme: expose subsystem type in sysfs attribute 'subsystype'
+
+    With unique discovery controller NQNs we cannot distinguish the
+    subsystem type by the NQN alone, but need to check the subsystem
+    type, too.
+    So expose the subsystem type in a new sysfs attribute 'subsystype'.
+
+    Signed-off-by: Hannes Reinecke <[email protected]>
+    Reviewed-by: Chaitanya Kulkarni <[email protected]>
+    Signed-off-by: Christoph Hellwig <[email protected]>
+
+
+commit 3ede8f72a9a2825efca23a3552e80a1202ea88fd
+Author: Martin Belanger <[email protected]>
+Date:   Thu May 20 15:09:34 2021 -0400
+
+    nvme-tcp: allow selecting the network interface for connections
+
+    In our application, we need a way to force TCP connections to go out a
+    specific IP interface instead of letting Linux select the interface
+    based on the routing tables.
+
+    Add the 'host-iface' option to allow specifying the interface to use.
+    When the option host-iface is specified, the driver uses the specified
+    interface to set the option SO_BINDTODEVICE on the TCP socket before
+    connecting.
+
+    This new option is needed in addtion to the existing host-traddr for
+    the following reasons:
+
+    Specifying an IP interface by its associated IP address is less
+    intuitive than specifying the actual interface name and, in some cases,
+    simply doesn't work. That's because the association between interfaces
+    and IP addresses is not predictable. IP addresses can be changed or can
+    change by themselves over time (e.g. DHCP). Interface names are
+    predictable [1] and will persist over time. Consider the following
+    configuration.
+
+    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state ...
+        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
+        inet 100.0.0.100/24 scope global lo
+           valid_lft forever preferred_lft forever
+    2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc ...
+        link/ether 08:00:27:21:65:ec brd ff:ff:ff:ff:ff:ff
+        inet 100.0.0.100/24 scope global enp0s3
+           valid_lft forever preferred_lft forever
+    3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc ...
+        link/ether 08:00:27:4f:95:5c brd ff:ff:ff:ff:ff:ff
+        inet 100.0.0.100/24 scope global enp0s8
+           valid_lft forever preferred_lft forever
+
+    The above is a VM that I configured with the same IP address
+    (100.0.0.100) on all interfaces. Doing a reverse lookup to identify the
+    unique interface associated with 100.0.0.100 does not work here. And
+    this is why the option host_iface is required. I understand that the
+    above config does not represent a standard host system, but I'm using
+    this to prove a point: "We can never know how users will configure
+    their systems". By te way, The above configuration is perfectly fine
+    by Linux.
+
+    The current TCP implementation for host_traddr performs a
+    bind()-before-connect(). This is a common construct to set the source
+    IP address on a TCP socket before connecting. This has no effect on how
+    Linux selects the interface for the connection. That's because Linux
+    uses the Weak End System model as described in RFC1122 [2]. On the other
+    hand, setting the Source IP Address has benefits and should be supported
+    by linux-nvme. In fact, setting the Source IP Address is a mandatory
+    FedGov requirement (e.g. connection to a RADIUS/TACACS+ server).
+    Consider the following configuration.
+
+    $ ip addr list dev enp0s8
+    3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc ...
+        link/ether 08:00:27:4f:95:5c brd ff:ff:ff:ff:ff:ff
+        inet 192.168.56.101/24 brd 192.168.56.255 scope global enp0s8
+           valid_lft 426sec preferred_lft 426sec
+        inet 192.168.56.102/24 scope global secondary enp0s8
+           valid_lft forever preferred_lft forever
+        inet 192.168.56.103/24 scope global secondary enp0s8
+           valid_lft forever preferred_lft forever
+        inet 192.168.56.104/24 scope global secondary enp0s8
+           valid_lft forever preferred_lft forever
+
+    Here we can see that several addresses are associated with interface
+    enp0s8. By default, Linux always selects the default IP address,
+    192.168.56.101, as the source address when connecting over interface
+    enp0s8. Some users, however, want the ability to specify a different
+    source address (e.g., 192.168.56.102, 192.168.56.103, ...). The option
+    host_traddr can be used as-is to perform this function.
+
+    In conclusion, I believe that we need 2 options for TCP connections.
+    One that can be used to specify an interface (host-iface). And one that
+    can be used to set the source address (host-traddr). Users should be
+    allowed to use one or the other, or both, or none. Of course, the
+    documentation for host_traddr will need some clarification. It should
+    state that when used for TCP connection, this option only sets the
+    source address. And the documentation for host_iface should say that
+    this option is only available for TCP connections.
+
+    References:
+    [1] 
https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/
+    [2] https://tools.ietf.org/html/rfc1122
+
+    Tested both IPv4 and IPv6 connections.
+
+    Signed-off-by: Martin Belanger <[email protected]>
+    Reviewed-by: Sagi Grimberg <[email protected]>
+    Reviewed-by: Hannes Reinecke <[email protected]>
+    Signed-off-by: Christoph Hellwig <[email protected]>
+```
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/Dockerfile 
new/nvme-stas-1.0~rc4/Dockerfile
--- old/nvme-stas-1.0~rc2/Dockerfile    2022-02-21 18:58:16.000000000 +0100
+++ new/nvme-stas-1.0~rc4/Dockerfile    2022-03-15 18:30:55.000000000 +0100
@@ -1,20 +1,3 @@
-##########################################################################################
-ARG registry=library
-ARG base=fedora
-ARG version=33
-FROM $registry/$base:$version as libnvme-builder
-
-WORKDIR /root
-
-# TODO: once libnvme project has a package or docker image, remove this stage 
and install libnvme
-RUN dnf install -y git gcc g++ cmake libuuid-devel json-c-devel swig 
python-devel meson
-ARG GITHUB_ORG=linux-nvme
-ARG GITHUB_REPO=libnvme
-ARG GITHUB_TOKEN
-RUN git clone https://${GITHUB_TOKEN}github.com/${GITHUB_ORG}/${GITHUB_REPO} 
&& \
-    cd ${GITHUB_REPO} && meson .build && ninja -C .build && cd .build && 
DESTDIR=/root/install meson install
-
-##########################################################################################
 ARG registry=library
 ARG base=fedora
 ARG version=33
@@ -22,9 +5,10 @@
 
 WORKDIR /root
 
-RUN dnf install -y python3-dasbus python3-pyudev python3-systemd 
python3-gobject meson
-# TODO: once libnvme project has a package, use: dnf install -y libnvme
-COPY --from=libnvme-builder /root/install /
+# for nvme-stas
+RUN dnf install -y python3-dasbus python3-pyudev python3-systemd 
python3-gobject python3-netifaces meson
+# for libnvme
+RUN dnf install -y git gcc g++ cmake openssl-devel libuuid-devel json-c-devel 
swig python-devel meson
 
 COPY . .
 RUN meson .build && ninja -C .build && cd .build && meson install
Binary files old/nvme-stas-1.0~rc2/Documentation/images/STAF-STAC-libnvme.png 
and new/nvme-stas-1.0~rc4/Documentation/images/STAF-STAC-libnvme.png differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/Makefile 
new/nvme-stas-1.0~rc4/Makefile
--- old/nvme-stas-1.0~rc2/Makefile      2022-02-21 18:58:16.000000000 +0100
+++ new/nvme-stas-1.0~rc4/Makefile      2022-03-15 18:30:55.000000000 +0100
@@ -12,7 +12,7 @@
 RPM-PKG-DIR   := ${BUILD-DIR}/rpm-pkg
 
 ${BUILD-DIR}:
-       ./configure
+       BUILD_DIR=${BUILD-DIR} ./configure
        @echo "Configuration located in: $@"
        @echo "-------------------------------------------------------"
 
@@ -32,7 +32,7 @@
        rm -rf ${BUILD-DIR}
 endif
 
-.PHONY: install
+.PHONY: install test
 install test: ${BUILD-DIR}
        cd ${BUILD-DIR} && meson $@
 
@@ -65,4 +65,4 @@
 
 .PHONY: rpm
 rpm: dist
-       rpmbuild ${BUILD-DIR}/nvme-stas.spec
+       rpmbuild -ba ${BUILD-DIR}/nvme-stas.spec
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/README.md 
new/nvme-stas-1.0~rc4/README.md
--- old/nvme-stas-1.0~rc2/README.md     2022-02-21 18:58:16.000000000 +0100
+++ new/nvme-stas-1.0~rc4/README.md     2022-03-15 18:30:55.000000000 +0100
@@ -84,18 +84,16 @@
 **Debian packages (tested on Ubuntu 20.04):**
 
 ```bash
-sudo apt-get install -y python3-pyudev python3-systemd python3-gi
+sudo apt-get install -y python3-pyudev python3-systemd python3-gi 
python3-netifaces
 sudo pip3 install dasbus
 ```
 
-**Yum packages (tested on Fedora 34):**
+**RPM packages (tested on Fedora 34..35 and SLES15):**
 
 ```bash
-sudo dnf install -y python3-dasbus python3-pyudev python3-systemd 
python3-gobject
+sudo dnf install -y python3-dasbus python3-pyudev python3-systemd 
python3-gobject python3-netifaces
 ```
 
-Additionally, the `libnvme` library (with Python bindings) needs to be 
installed. Currently only available from source at: 
https://github.com/linux-nvme/libnvme
-
 # STAF - STorage Appliance Finder
 
 
@@ -139,7 +137,7 @@
 
 # Build, install, unit tests
 
-STAS uses the `meson` build system. Since STAS is a Python project, there is 
no code to build. However, the code needs to be installed using `meson`. Once 
installed, unit tests can be run with `meson` as well.
+STAS uses the `meson` build system. Since STAS is a Python project, there is 
no code to build. However, the code needs to be installed using `meson`. Unit 
tests can also be run with `meson`.
 
 ## Using meson
 
@@ -149,16 +147,23 @@
 meson .build
 ```
 
-Note that the first line, `meson .build`, need only be called once. This 
analyzes the project and the host computer to determine if all the necessary 
tools are available. The result is in the directory named `.build`.
+The command `meson .build` need only be called once. This analyzes the project 
and the host computer to determine if all the necessary tools and dependencies 
are available. The result is saved to the directory named `.build`.
+
+To compile the code:
+
+```bash
+cd .build
+ninja
+```
 
-Do as follows to install the code:
+To install the code:
 
 ```bash
 cd .build
 meson install
 ```
 
-Do as follows to run the unit tests:
+To run the unit tests:
 
 ```bash
 cd .build
@@ -174,7 +179,7 @@
 make
 ```
 
-This performs the same operations as the meson approach described above. The 
`configure` script simply invokes `meson .build` and generates a `Makefile`. 
The generated `Makefile` provides the following operations.
+This performs the same operations as the meson approach described above. The 
`configure` script simply invokes `meson .build`.
 
 | make command       | Corresponding commands using meson                      
     |
 | ------------------ | 
------------------------------------------------------------ |
@@ -214,7 +219,7 @@
 
 ## Generating man and html pages
 
-nvme-stas uses the following programs to generate the documentation. These can 
be installed as shown in the "dependencies" section.
+nvme-stas uses the following programs to generate the documentation. These can 
be installed as shown in the "dependencies" section below.
 
 - `xsltproc` - Used to convert DocBook XML notation to "man pages" and "html 
pages".
 - `gdbus-codegen` - Used to convert D-Bus IDL to DocBook XML notation.
@@ -229,13 +234,13 @@
 sudo apt-get install -y docbook-xml docbook-xsl xsltproc libglib2.0-dev
 ```
 
-**Yum packages (tested on Fedora 34):**
+**RPM packages (tested on Fedora 34..35 and SLES15):**
 
 ```bash
 sudo dnf install -y docbook-style-xsl libxslt glib2-devel
 ```
 
-### Configuring to build the man and html pages
+### Configuring and building the man and html pages
 
 By default, the documentation is not built. You need to run the `configure`  
as follows to tell meson that you want to build the documentation. You may need 
to first purge any previous configuration.
 
@@ -245,7 +250,7 @@
 make
 ```
 
-
-
- 
-
+## Generating RPM and/or DEB packages
+```bash
+make rpm deb
+```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/configure 
new/nvme-stas-1.0~rc4/configure
--- old/nvme-stas-1.0~rc2/configure     2022-02-21 18:58:16.000000000 +0100
+++ new/nvme-stas-1.0~rc4/configure     2022-03-15 18:30:55.000000000 +0100
@@ -7,7 +7,7 @@
 #
 # Authors: Martin Belanger <[email protected]>
 #
-BUILD_DIR=".build"
+BUILD_DIR="${BUILD_DIR:-.build}"
 
 if [ ! -d ${BUILD_DIR} ]; then
     exec meson ${BUILD_DIR} "$@"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/debian/control 
new/nvme-stas-1.0~rc4/debian/control
--- old/nvme-stas-1.0~rc2/debian/control        2022-02-21 18:58:16.000000000 
+0100
+++ new/nvme-stas-1.0~rc4/debian/control        2022-03-15 18:30:55.000000000 
+0100
@@ -11,7 +11,7 @@
 
 Package: nvme-stas
 Architecture: all
-Depends: ${python3:Depends}, ${misc:Depends}, python3-pyudev, python3-systemd, 
python3-gi
+Depends: ${python3:Depends}, ${misc:Depends}, python3-pyudev, python3-systemd, 
python3-gi, python3-netifaces
 Description: NVMe STorage Appliance Services
  This package provides two daemons, stafd and stacd. The STorage Appliance
  Finder Daemon (stafd) automatically discovers NVMe-oF Discovery Controllers 
(DC)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/docker-compose.yml 
new/nvme-stas-1.0~rc4/docker-compose.yml
--- old/nvme-stas-1.0~rc2/docker-compose.yml    2022-02-21 18:58:16.000000000 
+0100
+++ new/nvme-stas-1.0~rc4/docker-compose.yml    2022-03-15 18:30:55.000000000 
+0100
@@ -12,7 +12,8 @@
         GITHUB_REPO: libnvme
         GITHUB_TOKEN:
     volumes:
-        - /run/dbus:/run/dbus      
+        - /run/dbus:/run/dbus
+        - /etc/nvme:/etc/nvme
     privileged: true
     network_mode: host
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/etc/stas/stacd.conf 
new/nvme-stas-1.0~rc4/etc/stas/stacd.conf
--- old/nvme-stas-1.0~rc2/etc/stas/stacd.conf   2022-02-21 18:58:16.000000000 
+0100
+++ new/nvme-stas-1.0~rc4/etc/stas/stacd.conf   2022-03-15 18:30:55.000000000 
+0100
@@ -39,6 +39,65 @@
 #              Unit:  Seconds
 #kato=120
 
+# ignore-iface: This option controls how connections with I/O Controllers (IOC)
+#               are made.
+#
+#               There is no guarantee that there will be a route to reach that
+#               IOC. However, we can use the socket option SO_BINDTODEVICE to
+#               force the connection to be made on a specific interface instead
+#               of letting the routing tables decide where to make the 
connection.
+#
+#               This option determines whether stacd will use SO_BINDTODEVICE 
to
+#               force connections on an interface or just rely on the routing
+#               tables. The default is to use SO_BINDTODEVICE, in other words,
+#               stacd does not ignore the interface.
+#
+#               BACKGROUND:
+#               By default, stacd will connect to IOCs on the same interface 
that
+#               was used to retrieve the discovery log pages. If stafd 
discovers
+#               a DC on an interface using mDNS, and stafd connects to that DC
+#               and retrieves the log pages, it is expected that the storage
+#               subsystems listed in the log pages are reachable on the same
+#               interface where the DC was discovered.
+#
+#               For example, let's say a DC is discovered on interface ens102.
+#               Then all the subsystems listed in the log pages retrieved from
+#               that DC must be reachable on interface ens102. If this doesn't
+#               work, for example you cannot "ping -I ens102 [storage-ip]", 
then
+#               the most likely explanation is that arp proxy is not enabled on
+#               the switch that the host is connected to on interface ens102.
+#               Whatever you do, resist the temptation to manually set up the
+#               routing tables or to add alternate routes going over a 
different
+#               interface than the one where the DC is located. That simply
+#               won't work. Make sure arp proxy is enabled on the switch first.
+#
+#               Setting routes won't work because, by default, stacd uses the
+#               SO_BINDTODEVICE socket option when it connects to IOCs. This
+#               option is used to force a socket connection to be made on a
+#               specific interface instead of letting the routing tables decide
+#               where to connect the socket. Even if you were to manually
+#               configure an alternate route on a different interface, the
+#               connections (i.e. host to IOC) will still be made on the
+#               interface where the DC was discovered by stafd.
+#
+#               Type:    boolean
+#               Range:   [false, true]
+#               Default: true
+#ignore-iface=false
+
+# ip-family: With this you can specify whether stacd will support IPv4, IPv6,
+#            or both when connecting to I/O Controllers (IOC). stacd will
+#            not try to connect to IP addresses (whether they come from the
+#            discovery log pages or manually configured with the 'controller'
+#            option defined below) if those IP addresses are disabled by this
+#            option. stacd will default to "ipv4+ipv6" if an invalid value is
+#            specified for this option.
+#
+#            Type:    String
+#            Range:   [ipv4, ipv6, ipv4+ipv6]
+#            Default: ipv4+ipv6
+#ip-family=ipv4+ipv6
+
 [Controllers]
 # controller: I/O Controllers (IOC) are specified with this keyword.
 #
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/etc/stas/stafd.conf 
new/nvme-stas-1.0~rc4/etc/stas/stafd.conf
--- old/nvme-stas-1.0~rc2/etc/stas/stafd.conf   2022-02-21 18:58:16.000000000 
+0100
+++ new/nvme-stas-1.0~rc4/etc/stas/stafd.conf   2022-03-15 18:30:55.000000000 
+0100
@@ -47,6 +47,42 @@
 #                         Range: [false, true]
 #persistent-connections=true
 
+# ignore-iface: This option controls how connections with Discovery Controllers
+#               (DC) are made.
+#
+#               DCs are automatically discovered using DNS-SD/mDNS. mDNS
+#               provides the DC's IP address and the interface on which the DC
+#               was discovered.
+#
+#               There is no guarantee that there will be a route to reach that
+#               DC. However, we can use the socket option SO_BINDTODEVICE to
+#               force the connection to be made on a specific interface instead
+#               of letting the routing tables decide where to make the
+#               connection.
+#
+#               This option determines whether stafd will use SO_BINDTODEVICE 
to
+#               force connections on an interface or just rely on the routing
+#               tables. The default is to use SO_BINDTODEVICE, in other words,
+#               stafd does not ignore the interface.
+#
+#               Type:    boolean
+#               Range:   [false, true]
+#               Default: false
+#ignore-iface=false
+
+# ip-family: With this you can specify whether stafd will support IPv4, IPv6,
+#            or both when connecting to Discovery Controllers (DC). stafd will
+#            not try to connect to IP addresses (whether discovered with mDNS
+#            or manually configured with the 'controller' option defined below)
+#            if those IP addresses are disabled by this option. stafd will
+#            default to "ipv4+ipv6" if an invalid value is specified for this
+#            option.
+#
+#            Type:    String
+#            Range:   [ipv4, ipv6, ipv4+ipv6]
+#            Default: ipv4+ipv6
+#ip-family=ipv4+ipv6
+
 [Service Discovery]
 # zeroconf: Control whether DNS-SD/mDNS automatic discovery is enabled. This is
 #           used to enable or disable automatic discovery of Discovery
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/man/stacd.conf.xml 
new/nvme-stas-1.0~rc4/man/stacd.conf.xml
--- old/nvme-stas-1.0~rc2/man/stacd.conf.xml    2022-02-21 18:58:16.000000000 
+0100
+++ new/nvme-stas-1.0~rc4/man/stacd.conf.xml    2022-03-15 18:30:55.000000000 
+0100
@@ -83,6 +83,78 @@
                 <xi:include href="standard-conf.xml" xpointer="hdr-digest"/>
                 <xi:include href="standard-conf.xml" xpointer="data-digest"/>
                 <xi:include href="standard-conf.xml" xpointer="kato"/>
+                <xi:include href="standard-conf.xml" xpointer="ip-family"/>
+
+                <varlistentry>
+                    <term><varname>ignore-iface=</varname></term>
+                    <listitem>
+                        <para>
+                            Takes a boolean argument. This option controls how
+                            connections with I/O Controllers (IOC) are made.
+                        </para>
+
+                        <para>
+                            There is no guarantee that there will be a route to
+                            reach that IOC. However, we can use the socket
+                            option SO_BINDTODEVICE to force the connection to 
be
+                            made on a specific interface instead of letting the
+                            routing tables decide where to make the connection.
+                        </para>
+
+                        <para>
+                            This option determines whether <code>stacd</code> 
will use
+                            SO_BINDTODEVICE to force connections on an 
interface
+                            or just rely on the routing tables. The default is
+                            to use SO_BINDTODEVICE, in other words, 
<code>stacd</code> does
+                            not ignore the interface.
+                        </para>
+
+                        <para>
+                            BACKGROUND:
+                            By default, <code>stacd</code> will connect to 
IOCs on the same
+                            interface that was used to retrieve the discovery
+                            log pages. If stafd discovers a DC on an interface
+                            using mDNS, and stafd connects to that DC and
+                            retrieves the log pages, it is expected that the
+                            storage subsystems listed in the log pages are
+                            reachable on the same interface where the DC was
+                            discovered.
+                        </para>
+
+                        <para>
+                            For example, let's say a DC is discovered on
+                            interface ens102. Then all the subsystems listed in
+                            the log pages retrieved from that DC must be
+                            reachable on interface ens102. If this doesn't 
work,
+                            for example you cannot "ping -I ens102 
[storage-ip]",
+                            then the most likely explanation is that arp proxy
+                            is not enabled on the switch that the host is
+                            connected to on interface ens102. Whatever you do,
+                            resist the temptation to manually set up the 
routing
+                            tables or to add alternate routes going over a
+                            different interface than the one where the DC is
+                            located. That simply won't work. Make sure arp 
proxy
+                            is enabled on the switch first.
+                        </para>
+
+                        <para>
+                            Setting routes won't work because, by default, 
<code>stacd</code>
+                            uses the SO_BINDTODEVICE socket option when it
+                            connects to IOCs. This option is used to force a
+                            socket connection to be made on a specific 
interface
+                            instead of letting the routing tables decide where
+                            to connect the socket. Even if you were to manually
+                            configure an alternate route on a different 
interface,
+                            the connections (i.e. host to IOC) will still be
+                            made on the interface where the DC was discovered 
by
+                            stafd.
+                        </para>
+
+                        <para>
+                            Defaults to <literal>false</literal>.
+                        </para>
+                    </listitem>
+                </varlistentry>
             </variablelist>
         </refsect2>
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/man/stafd.conf.xml 
new/nvme-stas-1.0~rc4/man/stafd.conf.xml
--- old/nvme-stas-1.0~rc2/man/stafd.conf.xml    2022-02-21 18:58:16.000000000 
+0100
+++ new/nvme-stas-1.0~rc4/man/stafd.conf.xml    2022-03-15 18:30:55.000000000 
+0100
@@ -84,6 +84,7 @@
                 <xi:include href="standard-conf.xml" xpointer="hdr-digest"/>
                 <xi:include href="standard-conf.xml" xpointer="data-digest"/>
                 <xi:include href="standard-conf.xml" xpointer="kato"/>
+                <xi:include href="standard-conf.xml" xpointer="ip-family"/>
 
                 <varlistentry>
                     <term><varname>persistent-connections=</varname></term>
@@ -95,7 +96,43 @@
                             even when stafd is stopped. When
                             <literal>false</literal>, <code>stafd</code>
                             will disconnect from all DCs it is connected to on
-                            exit. Defaults to<literal>false</literal>.
+                            exit. Defaults to <literal>false</literal>.
+                        </para>
+                    </listitem>
+                </varlistentry>
+
+                <varlistentry>
+                    <term><varname>ignore-iface=</varname></term>
+                    <listitem>
+                        <para>
+                            Takes a boolean argument. This option controls how
+                            connections with Discovery Controllers (DC) are 
made.
+                        </para>
+
+                        <para>
+                            DCs are automatically discovered using DNS-SD/mDNS.
+                            mDNS provides the DC's IP address and the interface
+                            on which the DC was discovered.
+                        </para>
+
+                        <para>
+                            There is no guarantee that there will be a route to
+                            reach that DC. However, we can use the socket 
option
+                            SO_BINDTODEVICE to force the connection to be made
+                            on a specific interface instead of letting the
+                            routing tables decide where to make the connection.
+                        </para>
+
+                        <para>
+                            This option determines whether <code>stafd</code>
+                            will use SO_BINDTODEVICE to force connections on an
+                            interface or just rely on the routing tables. The
+                            default is to use SO_BINDTODEVICE, in other words,
+                            <code>stafd</code> does not ignore the interface by
+                            default.
+                        </para>
+                        <para>
+                            Defaults to <literal>false</literal>.
                         </para>
                     </listitem>
                 </varlistentry>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/man/standard-conf.xml 
new/nvme-stas-1.0~rc4/man/standard-conf.xml
--- old/nvme-stas-1.0~rc2/man/standard-conf.xml 2022-02-21 18:58:16.000000000 
+0100
+++ new/nvme-stas-1.0~rc4/man/standard-conf.xml 2022-03-15 18:30:55.000000000 
+0100
@@ -64,6 +64,30 @@
                 </para>
             </listitem>
         </varlistentry>
+
+        <varlistentry id='ip-family'>
+            <term><varname>ip-family=</varname></term>
+
+            <listitem id='ip-family-text'>
+                <para>
+                    Takes a string argument. With this you can specify
+                    whether IPv4, IPv6, or both are supported when
+                    connecting to a Controller. Connections will not be
+                    attempted to IP addresses (whether discovered or
+                    manually configured with the 'controller') if those
+                    IP addresses are disabled by this option. If an invalid
+                    value is entered, then "ipv4+ipv6" will be used by default.
+                </para>
+
+                <para>
+                    Choices are <literal>ipv4</literal>, 
<literal>ipv6</literal>, or <literal>ipv4+ipv6</literal>.
+                </para>
+
+                <para>
+                    Defaults to <literal>ipv4+ipv6</literal>.
+                </para>
+            </listitem>
+        </varlistentry>
     </variablelist>
 
     <refsect2 id='controller'>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/meson.build 
new/nvme-stas-1.0~rc4/meson.build
--- old/nvme-stas-1.0~rc2/meson.build   2022-02-21 18:58:16.000000000 +0100
+++ new/nvme-stas-1.0~rc4/meson.build   2022-03-15 18:30:55.000000000 +0100
@@ -17,6 +17,7 @@
     ]
 )
 
+#===============================================================================
 prefix  = get_option('prefix')
 etcdir  = get_option('sysconfdir')
 datadir = get_option('datadir')
@@ -28,6 +29,9 @@
 want_man  = get_option('man')
 want_html = get_option('html')
 
+# Check for libnvme availability
+libnvme_dep = dependency('libnvme', fallback : ['libnvme', 'libnvme_dep'])
+
 # Check that we have all the right Python3 dependencies
 python3 = import('python').find_installation('python3')
 python_version = python3.language_version()
@@ -39,11 +43,11 @@
 check_pymodules = get_option('check_pymodules')
 if check_pymodules
     py_modules_reqd = [
-        ['libnvme', 'This library must be installed from sources (at this 
time)'],
-        ['dasbus',  'Install python3-dasbus (rpm) OR pip3 install dasbus'],
-        ['pyudev',  'Install python3-pyudev (deb/rpm)'],
-        ['systemd', 'Install python3-systemd (deb/rpm)'],
-        ['gi',      'Install python3-gi (deb) OR python3-gobject (rpm)'],
+        ['dasbus',    'Install python3-dasbus (rpm) OR pip3 install dasbus'],
+        ['pyudev',    'Install python3-pyudev (deb/rpm)'],
+        ['netifaces', 'Install python3-netifaces (deb/rpm)'],
+        ['systemd',   'Install python3-systemd (deb/rpm)'],
+        ['gi',        'Install python3-gi (deb) OR python3-gobject (rpm)'],
     ]
     if want_man or want_html
         py_modules_reqd += [['lxml', 'Install python3-lxml (deb/rpm)']]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/nvme-stas.spec.in 
new/nvme-stas-1.0~rc4/nvme-stas.spec.in
--- old/nvme-stas-1.0~rc2/nvme-stas.spec.in     2022-02-21 18:58:16.000000000 
+0100
+++ new/nvme-stas-1.0~rc4/nvme-stas.spec.in     2022-03-15 18:30:55.000000000 
+0100
@@ -12,6 +12,14 @@
 
 BuildRequires: meson
 BuildRequires: python3-devel
+BuildRequires: python3-libnvme
+BuildRequires: systemd-rpm-macros
+Requires:      python3-libnvme
+Requires:      python3-dasbus
+Requires:      python3-pyudev
+Requires:      python3-systemd
+Requires:      python3-gobject
+Requires:      python3-netifaces
 
 %description
 NVMe STorage Appliance Services
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/stacctl.py 
new/nvme-stas-1.0~rc4/stacctl.py
--- old/nvme-stas-1.0~rc2/stacctl.py    2022-02-21 18:58:16.000000000 +0100
+++ new/nvme-stas-1.0~rc4/stacctl.py    2022-03-15 18:30:55.000000000 +0100
@@ -70,7 +70,8 @@
 
 try:
     ARGS.func(ARGS)
-except dasbus.error.DBusError as ex:
-    sys.exit(f'{ex}')
-except AttributeError as ex:
-    sys.exit(f'{ex}')
+except dasbus.error.DBusError:
+    sys.exit(f'Unable to communicate with {defs.STACD_PROCNAME} over D-Bus. Is 
{defs.STACD_PROCNAME} running?')
+except AttributeError:
+    PARSER.print_help()
+    sys.exit()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/stacd.py 
new/nvme-stas-1.0~rc4/stacd.py
--- old/nvme-stas-1.0~rc2/stacd.py      2022-02-21 18:58:16.000000000 +0100
+++ new/nvme-stas-1.0~rc4/stacd.py      2022-03-15 18:30:55.000000000 +0100
@@ -89,8 +89,13 @@
 
 SYS_CNF   = stas.get_sysconf() # Singleton
 NVME_ROOT = nvme.root()        # Singleton
+NVME_ROOT.log_level("debug" if (ARGS.tron or CNF.tron) else "err")
 NVME_HOST = nvme.host(NVME_ROOT, SYS_CNF.hostnqn, SYS_CNF.hostid, 
SYS_CNF.hostsymname) # Singleton
 
+def set_loglevel(tron):
+    stas.trace_control(tron)
+    NVME_ROOT.log_level("debug" if tron else "err")
+
 
#*******************************************************************************
 class Ioc(stas.Controller):
     ''' @brief This object establishes a connection to one I/O Controller.
@@ -132,7 +137,7 @@
         @tron.setter
         def tron(self, value): # pylint: disable=no-self-use
             ''' @brief Set Trace ON property '''
-            stas.trace_control(value)
+            set_loglevel(value)
 
         @property
         def log_level(self) -> str:
@@ -198,7 +203,7 @@
         '''
         systemd.daemon.notify('RELOADING=1')
         CNF.reload()
-        stas.trace_control(CNF.tron)
+        set_loglevel(CNF.tron)
         self._cfg_soak_tmr.start(Stac.CONF_STABILITY_SOAK_TIME_SEC)
         systemd.daemon.notify('READY=1')
         return GLib.SOURCE_CONTINUE
@@ -218,6 +223,7 @@
         LOG.debug('Stac._config_ctrls_finish()        - discovered_ctrl_list = 
%s', discovered_ctrl_list)
 
         controllers = stas.remove_blacklisted(configured_ctrl_list + 
discovered_ctrl_list)
+        controllers = stas.remove_invalid_addresses(controllers)
 
         new_controller_ids = { stas.TransportId(controller) for controller in 
controllers }
         cur_controller_ids = set(self._controllers.keys())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/stafctl.py 
new/nvme-stas-1.0~rc4/stafctl.py
--- old/nvme-stas-1.0~rc2/stafctl.py    2022-02-21 18:58:16.000000000 +0100
+++ new/nvme-stas-1.0~rc4/stafctl.py    2022-03-15 18:30:55.000000000 +0100
@@ -96,7 +96,8 @@
 
 try:
     ARGS.func(ARGS)
-except dasbus.error.DBusError as ex:
-    sys.exit(f'{ex}')
-except AttributeError as ex:
-    sys.exit(f'{ex}')
+except dasbus.error.DBusError:
+    sys.exit(f'Unable to communicate with {defs.STAFD_PROCNAME} over D-Bus. Is 
{defs.STAFD_PROCNAME} running?')
+except AttributeError:
+    PARSER.print_help()
+    sys.exit()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/stafd.py 
new/nvme-stas-1.0~rc4/stafd.py
--- old/nvme-stas-1.0~rc2/stafd.py      2022-02-21 18:58:16.000000000 +0100
+++ new/nvme-stas-1.0~rc4/stafd.py      2022-03-15 18:30:55.000000000 +0100
@@ -112,8 +112,13 @@
 
 SYS_CNF   = stas.get_sysconf() # Singleton
 NVME_ROOT = nvme.root()        # Singleton
+NVME_ROOT.log_level("debug" if (ARGS.tron or CNF.tron) else "err")
 NVME_HOST = nvme.host(NVME_ROOT, SYS_CNF.hostnqn, SYS_CNF.hostid, 
SYS_CNF.hostsymname) # Singleton
 
+def set_loglevel(tron):
+    stas.trace_control(tron)
+    NVME_ROOT.log_level("debug" if tron else "err")
+
 
#*******************************************************************************
 class Dc(stas.Controller):
     ''' @brief This object establishes a connection to one Discover Controller 
(DC).
@@ -322,7 +327,7 @@
         @tron.setter
         def tron(self, value): # pylint: disable=no-self-use
             ''' @brief Set Trace ON property '''
-            stas.trace_control(value)
+            set_loglevel(value)
 
         @property
         def log_level(self) -> str:
@@ -398,7 +403,7 @@
         '''
         systemd.daemon.notify('RELOADING=1')
         CNF.reload()
-        stas.trace_control(CNF.tron)
+        set_loglevel(CNF.tron)
         self._avahi.config_stypes(CNF.get_stypes())
         self._cfg_soak_tmr.start()
         systemd.daemon.notify('READY=1')
@@ -430,6 +435,7 @@
         LOG.debug('Staf._config_ctrls_finish()        - referral_ctrl_list    
= %s', referral_ctrl_list)
 
         controllers = stas.remove_blacklisted(configured_ctrl_list + 
discovered_ctrl_list + referral_ctrl_list)
+        controllers = stas.remove_invalid_addresses(controllers)
 
         new_controller_ids = { stas.TransportId(controller) for controller in 
controllers }
         cur_controller_ids = set(self._controllers.keys())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/staslib/stas.py 
new/nvme-stas-1.0~rc4/staslib/stas.py
--- old/nvme-stas-1.0~rc2/staslib/stas.py       2022-02-21 18:58:16.000000000 
+0100
+++ new/nvme-stas-1.0~rc4/staslib/stas.py       2022-03-15 18:30:55.000000000 
+0100
@@ -16,6 +16,8 @@
 import logging as LG
 import configparser
 import platform
+import ipaddress
+import netifaces
 import pyudev
 import systemd.daemon
 import dasbus.connection
@@ -150,6 +152,8 @@
             ('Global', 'hdr-digest'): 'false',
             ('Global', 'data-digest'): 'false',
             ('Global', 'kato'): None,
+            ('Global', 'ignore-iface'): 'false',
+            ('Global', 'ip-family'): 'ipv4+ipv6',
             ('Service Discovery', 'zeroconf'): 'enabled',
             ('Controllers', 'controller'): list(),
             ('Controllers', 'blacklist'): list(),
@@ -163,22 +167,52 @@
         self._config = self.read_conf_file()
 
     @property
+    def conf_file(self):
+        return self._conf_file
+
+    @property
     def tron(self):
         ''' @brief return the "tron" config parameter
         '''
-        return self.__get_value('Global', 'tron')[0] == 'true'
+        return self.__get_bool('Global', 'tron')
 
     @property
     def hdr_digest(self):
         ''' @brief return the "hdr-digest" config parameter
         '''
-        return self.__get_value('Global', 'hdr-digest')[0] == 'true'
+        return self.__get_bool('Global', 'hdr-digest')
 
     @property
     def data_digest(self):
         ''' @brief return the "data-digest" config parameter
         '''
-        return self.__get_value('Global', 'data-digest')[0] == 'true'
+        return self.__get_bool('Global', 'data-digest')
+
+    @property
+    def persistent_connections(self):
+        ''' @brief return the "persistent-connections" config parameter
+        '''
+        return self.__get_bool('Global', 'persistent-connections')
+
+    @property
+    def ignore_iface(self):
+        ''' @brief return the "ignore-iface" config parameter
+        '''
+        return self.__get_bool('Global', 'ignore-iface')
+
+    @property
+    def ip_family(self):
+        ''' @brief return the "ip-family" config parameter.
+            @rtype tuple
+        '''
+        family = self.__get_value('Global', 'ip-family')[0]
+
+        if family == 'ipv4':
+            return (4, )
+        if family == 'ipv6':
+            return (6, )
+
+        return (4, 6)
 
     @property
     def kato(self):
@@ -187,12 +221,6 @@
         kato = self.__get_value('Global', 'kato')[0]
         return None if kato is None else int(kato)
 
-    @property
-    def persistent_connections(self):
-        ''' @brief return the "persistent-connections" config parameter
-        '''
-        return self.__get_value('Global', 'persistent-connections')[0] == 
'true'
-
     def get_controllers(self):
         ''' @brief Return the list of controllers in the config file.
                    Each controller is in the form of a dictionary as follows.
@@ -256,6 +284,9 @@
             config.read(self._conf_file)
         return config
 
+    def __get_bool(self, section, option):
+        return self.__get_value(section, option)[0] == 'true'
+
     def __get_value(self, section, option):
         try:
             value = self._config.get(section=section, option=option)
@@ -303,6 +334,9 @@
         except FileNotFoundError as ex:
             sys.exit('Error reading mandatory Host NQN (see stasadm --help): 
%s', ex)
 
+        if not value.startswith('nqn.'):
+            sys.exit('Error Host NQN "%s" should start with "nqn."', value)
+
         return value
 
     @property
@@ -604,6 +638,13 @@
             @return The device if a match is found, None otherwise.
         '''
         for device in self._context.list_devices(subsystem='nvme', 
NVME_TRADDR=tid.traddr, NVME_TRSVCID=tid.trsvcid, NVME_TRTYPE=tid.transport):
+            # Note: Prior to 5.18 linux didn't expose the cntrltype through
+            # the sysfs. So, this may return None on older kernels.
+            cntrltype = device.attributes.get('cntrltype')
+            if cntrltype is not None and cntrltype.decode() != 'discovery':
+                continue
+
+            # Imply Discovery controller based on the absence of children.
             # Discovery Controllers have no children devices
             if len(list(device.children)) != 0:
                 continue
@@ -617,6 +658,13 @@
 
     def find_nvme_ioc_device(self, tid):
         for device in self._context.list_devices(subsystem='nvme', 
NVME_TRADDR=tid.traddr, NVME_TRSVCID=tid.trsvcid, NVME_TRTYPE=tid.transport):
+            # Note: Prior to 5.18 linux didn't expose the cntrltype through
+            # the sysfs. So, this may return None on older kernels.
+            cntrltype = device.attributes.get('cntrltype')
+            if cntrltype is not None and cntrltype.decode() != 'io':
+                continue
+
+            # Imply I/O controller based on the presence of children.
             # I/O Controllers have children devices
             if len(list(device.children)) == 0:
                 continue
@@ -689,6 +737,44 @@
     return controllers
 
 
#*******************************************************************************
+def remove_invalid_addresses(controllers:list):
+    valid_controllers = list()
+    for controller in controllers:
+        # First, let's make sure that traddr is
+        # syntactically a valid IPv4 or IPv6 address.
+        traddr = controller.get('traddr')
+        try:
+            ip = ipaddress.ip_address(traddr)
+        except ValueError:
+            LOG.warning('%s IP address is not valid', TransportId(controller))
+            continue
+
+        if ip.version not in CNF.ip_family:
+            LOG.debug('%s ignored because IPv%s is disabled in %s',
+                      TransportId(controller), ip.version, CNF.conf_file)
+            continue
+
+        # Next, if the interface is not specified, we'll assume that the
+        # IP address is valid and that there is a route to reach traddr.
+        iface = controller.get('host-iface')
+        if not iface:
+            valid_controllers.append(controller)
+        else:
+            # Finally, if there is an interface specified, let's make sure
+            # that the interface is enabled to connect using traddr. In other
+            # words, if traddr is an IPv4 address, then the interface must have
+            # IPv4 enabled. Same logic applies to IPv6.
+            ifaddresses = netifaces.ifaddresses(iface) # List of IP addresses 
configured on the interface
+            if ( (ip.version == 4 and netifaces.AF_INET in ifaddresses) or
+                 (ip.version == 6 and netifaces.AF_INET6 in ifaddresses) ):
+                valid_controllers.append(controller)
+            else:
+                LOG.warning('%s rejected because interface %s is not 
configured for IPv%s',
+                            TransportId(controller), iface, ip.version)
+
+    return valid_controllers
+
+#*******************************************************************************
 class TransportId:
     # pylint: disable=too-many-instance-attributes
     ''' Transport Identifier
@@ -713,7 +799,7 @@
         trsvcid = cid.get('trsvcid')
         self._trsvcid     = trsvcid if trsvcid else (TransportId.RDMA_IP_PORT 
if self._transport == 'rdma' else TransportId.DISC_IP_PORT) # pylint: 
disable=used-before-assignment
         self._host_traddr = cid.get('host-traddr', '')
-        self._host_iface  = cid.get('host-iface', '')
+        self._host_iface  = '' if CNF.ignore_iface else cid.get('host-iface', 
'')
         self._subsysnqn   = cid.get('subsysnqn')
         self._key         = (self._transport, self._traddr, self._trsvcid, 
self._host_traddr, self._host_iface, self._subsysnqn)
         self._hash        = hash(self._key)
@@ -798,7 +884,7 @@
 
         def addr_resolved(resolver, result, indx):
             hostname = controllers[indx]['traddr']
-            traddr = None
+            traddr = hostname
             try:
                 addresses = resolver.lookup_by_name_finish(result)
                 if addresses:
@@ -1081,7 +1167,9 @@
     def _try_to_connect(self):
         self._connect_attempts += 1
 
-        host_iface = self.tid.host_iface if self.tid.host_iface and 
get_nvme_options().host_iface_supp else None
+        host_iface = self.tid.host_iface if (self.tid.host_iface and
+                                             not CNF.ignore_iface and
+                                             
get_nvme_options().host_iface_supp) else None
         self._ctrl = nvme.ctrl(self._root, subsysnqn=self.tid.subsysnqn,
                                transport=self.tid.transport,
                                traddr=self.tid.traddr,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/nvme-stas-1.0~rc2/subprojects/libnvme.wrap 
new/nvme-stas-1.0~rc4/subprojects/libnvme.wrap
--- old/nvme-stas-1.0~rc2/subprojects/libnvme.wrap      1970-01-01 
01:00:00.000000000 +0100
+++ new/nvme-stas-1.0~rc4/subprojects/libnvme.wrap      2022-03-15 
18:30:55.000000000 +0100
@@ -0,0 +1,6 @@
+[wrap-git]
+url = https://github.com/linux-nvme/libnvme.git
+revision = 3a1bc6c6226d240b544058065382e2546018caa8
+
+[provide]
+libnvme = libnvme_dep

++++++ nvme-stas.obsinfo ++++++
--- /var/tmp/diff_new_pack.0VCu6Z/_old  2022-03-23 20:20:25.270532103 +0100
+++ /var/tmp/diff_new_pack.0VCu6Z/_new  2022-03-23 20:20:25.274532105 +0100
@@ -1,5 +1,5 @@
 name: nvme-stas
-version: 1.0~rc2
-mtime: 1645466296
-commit: 025e126c568d0103f4d6a26a5392182603b358e3
+version: 1.0~rc4
+mtime: 1647365455
+commit: 3fe9da46822603ff3dafb5c8708a1856580df2e5
 

Reply via email to