[ovs-dev,1/4] ovs-kmod-ctl: introduce a kernel module load script
diff mbox series

Message ID 20180320210518.9982-2-aconole@redhat.com
State Changes Requested
Headers show
Series
  • selinux: introduce a transition domain for loading kmods
Related show

Commit Message

Aaron Conole March 20, 2018, 9:05 p.m. UTC
Currently, Open vSwitch on linux embeds the logic of loading and unloading
kernel modules into the ovs-ctl and ovs-lib script files.  This works, but
it means that there is no way to leverage extended filesystem attributes
to grant fine grain permissions relating to module loading.

The split out utility 'ovs-kmod-ctl' will be used in an upcoming commit
for RHEL-based distributions to have a separate transition domain that
will allow module loading to be given to a separate selinux domain from
the openvswitch_t domain.

Signed-off-by: Aaron Conole <aconole@redhat.com>
---
 debian/openvswitch-switch.install  |   1 +
 debian/openvswitch-switch.manpages |   1 +
 rhel/openvswitch-fedora.spec.in    |   2 +
 rhel/openvswitch.spec.in           |   2 +
 utilities/.gitignore               |   1 +
 utilities/automake.mk              |   5 +
 utilities/ovs-ctl.in               |  32 +-----
 utilities/ovs-kmod-ctl.8           | 103 +++++++++++++++++
 utilities/ovs-kmod-ctl.in          | 228 +++++++++++++++++++++++++++++++++++++
 utilities/ovs-lib.in               |  12 +-
 10 files changed, 350 insertions(+), 37 deletions(-)
 create mode 100644 utilities/ovs-kmod-ctl.8
 create mode 100644 utilities/ovs-kmod-ctl.in

Comments

Ansis Atteka March 26, 2018, 9:23 p.m. UTC | #1
On 20 March 2018 at 14:05, Aaron Conole <aconole@redhat.com> wrote:
> Currently, Open vSwitch on linux embeds the logic of loading and unloading
> kernel modules into the ovs-ctl and ovs-lib script files.  This works, but
> it means that there is no way to leverage extended filesystem attributes
> to grant fine grain permissions relating to module loading.
>
> The split out utility 'ovs-kmod-ctl' will be used in an upcoming commit
> for RHEL-based distributions to have a separate transition domain that
> will allow module loading to be given to a separate selinux domain from
> the openvswitch_t domain.
>
> Signed-off-by: Aaron Conole <aconole@redhat.com>
> ---
>  debian/openvswitch-switch.install  |   1 +
>  debian/openvswitch-switch.manpages |   1 +
>  rhel/openvswitch-fedora.spec.in    |   2 +
>  rhel/openvswitch.spec.in           |   2 +
>  utilities/.gitignore               |   1 +
>  utilities/automake.mk              |   5 +
>  utilities/ovs-ctl.in               |  32 +-----
>  utilities/ovs-kmod-ctl.8           | 103 +++++++++++++++++
>  utilities/ovs-kmod-ctl.in          | 228 +++++++++++++++++++++++++++++++++++++
>  utilities/ovs-lib.in               |  12 +-
>  10 files changed, 350 insertions(+), 37 deletions(-)
>  create mode 100644 utilities/ovs-kmod-ctl.8
>  create mode 100644 utilities/ovs-kmod-ctl.in
>
> diff --git a/debian/openvswitch-switch.install b/debian/openvswitch-switch.install
> index bfb391fe8..6a6e9a543 100644
> --- a/debian/openvswitch-switch.install
> +++ b/debian/openvswitch-switch.install
> @@ -12,5 +12,6 @@ usr/sbin/ovs-vswitchd
>  usr/sbin/ovsdb-server
>  usr/share/openvswitch/scripts/ovs-check-dead-ifs
>  usr/share/openvswitch/scripts/ovs-ctl
> +usr/share/openvswitch/scripts/ovs-kmod-ctl
>  usr/share/openvswitch/scripts/ovs-save
>  usr/share/openvswitch/vswitch.ovsschema
> diff --git a/debian/openvswitch-switch.manpages b/debian/openvswitch-switch.manpages
> index a2f661a3e..47a1ba174 100644
> --- a/debian/openvswitch-switch.manpages
> +++ b/debian/openvswitch-switch.manpages
> @@ -2,6 +2,7 @@ ovsdb/ovsdb-server.1
>  utilities/ovs-ctl.8
>  utilities/ovs-dpctl-top.8
>  utilities/ovs-dpctl.8
> +utilities/ovs-kmod-ctl.8
>  utilities/ovs-pcap.1
>  utilities/ovs-tcpdump.8
>  utilities/ovs-tcpundump.1
> diff --git a/rhel/openvswitch-fedora.spec.in b/rhel/openvswitch-fedora.spec.in
> index 8a804942b..8fbc985ce 100644
> --- a/rhel/openvswitch-fedora.spec.in
> +++ b/rhel/openvswitch-fedora.spec.in
> @@ -542,6 +542,7 @@ fi
>  %{_datadir}/openvswitch/scripts/ovs-save
>  %{_datadir}/openvswitch/scripts/ovs-vtep
>  %{_datadir}/openvswitch/scripts/ovs-ctl
> +%{_datadir}/openvswitch/scripts/ovs-kmod-ctl
>  %{_datadir}/openvswitch/scripts/ovs-systemd-reload
>  %config %{_datadir}/openvswitch/vswitch.ovsschema
>  %config %{_datadir}/openvswitch/vtep.ovsschema
> @@ -574,6 +575,7 @@ fi
>  %{_mandir}/man8/ovs-ctl.8*
>  %{_mandir}/man8/ovs-dpctl.8*
>  %{_mandir}/man8/ovs-dpctl-top.8*
> +%{_mandir}/man8/ovs-kmod-ctl.8*
>  %{_mandir}/man8/ovs-ofctl.8*
>  %{_mandir}/man8/ovs-pki.8*
>  %{_mandir}/man8/ovs-vsctl.8*
> diff --git a/rhel/openvswitch.spec.in b/rhel/openvswitch.spec.in
> index 876990698..71d5afbdb 100644
> --- a/rhel/openvswitch.spec.in
> +++ b/rhel/openvswitch.spec.in
> @@ -236,6 +236,7 @@ exit 0
>  /usr/share/man/man8/ovs-ctl.8.gz
>  /usr/share/man/man8/ovs-dpctl.8.gz
>  /usr/share/man/man8/ovs-dpctl-top.8.gz
> +/usr/share/man/man8/ovs-kmod-ctl.8.gz
>  /usr/share/man/man8/ovs-ofctl.8.gz
>  /usr/share/man/man8/ovs-parse-backtrace.8.gz
>  /usr/share/man/man8/ovs-pki.8.gz
> @@ -249,6 +250,7 @@ exit 0
>  /usr/share/openvswitch/scripts/ovs-bugtool-*
>  /usr/share/openvswitch/scripts/ovs-check-dead-ifs
>  /usr/share/openvswitch/scripts/ovs-ctl
> +/usr/share/openvswitch/scripts/ovs-kmod-ctl
>  /usr/share/openvswitch/scripts/ovs-lib
>  /usr/share/openvswitch/scripts/ovs-save
>  /usr/share/openvswitch/scripts/ovs-vtep
> diff --git a/utilities/.gitignore b/utilities/.gitignore
> index 34c58f20f..eb2a69bf3 100644
> --- a/utilities/.gitignore
> +++ b/utilities/.gitignore
> @@ -13,6 +13,7 @@
>  /ovs-dpctl.8
>  /ovs-dpctl-top
>  /ovs-dpctl-top.8
> +/ovs-kmod-ctl
>  /ovs-l3ping
>  /ovs-l3ping.8
>  /ovs-lib
> diff --git a/utilities/automake.mk b/utilities/automake.mk
> index 60cf1c5ed..d8f2374a3 100644
> --- a/utilities/automake.mk
> +++ b/utilities/automake.mk
> @@ -20,6 +20,7 @@ endif
>  scripts_SCRIPTS += \
>         utilities/ovs-check-dead-ifs \
>         utilities/ovs-ctl \
> +       utilities/ovs-kmod-ctl \
>         utilities/ovs-save
>  scripts_DATA += utilities/ovs-lib
>
> @@ -44,6 +45,7 @@ EXTRA_DIST += \
>         utilities/ovs-dev.py \
>         utilities/ovs-docker \
>         utilities/ovs-dpctl-top.in \
> +       utilities/ovs-kmod-ctl.in \
>         utilities/ovs-l3ping.in \
>         utilities/ovs-lib.in \
>         utilities/ovs-parse-backtrace.in \
> @@ -63,6 +65,7 @@ MAN_ROOTS += \
>         utilities/ovs-ctl.8 \
>         utilities/ovs-dpctl.8.in \
>         utilities/ovs-dpctl-top.8.in \
> +       utilities/ovs-kmod-ctl.8 \
>         utilities/ovs-l3ping.8.in \
>         utilities/ovs-ofctl.8.in \
>         utilities/ovs-parse-backtrace.8 \
> @@ -81,6 +84,7 @@ CLEANFILES += \
>         utilities/ovs-dpctl.8 \
>         utilities/ovs-dpctl-top \
>         utilities/ovs-dpctl-top.8 \
> +       utilities/ovs-kmod-ctl \
>         utilities/ovs-l3ping \
>         utilities/ovs-l3ping.8 \
>         utilities/ovs-lib \
> @@ -107,6 +111,7 @@ man_MANS += \
>         utilities/ovs-testcontroller.8 \
>         utilities/ovs-dpctl.8 \
>         utilities/ovs-dpctl-top.8 \
> +       utilities/ovs-kmod-ctl.8 \
>         utilities/ovs-l3ping.8 \
>         utilities/ovs-ofctl.8 \
>         utilities/ovs-parse-backtrace.8 \
> diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in
> index ef06dd967..8fdf8909a 100755
> --- a/utilities/ovs-ctl.in
> +++ b/utilities/ovs-ctl.in
> @@ -30,37 +30,9 @@ done
>  ## start ##
>  ## ----- ##
>
> -insert_mods () {
> -    # Try loading openvswitch again.
> -    action "Inserting openvswitch module" modprobe openvswitch
> -}
> -
>  insert_mod_if_required () {
> -    # If this kernel has no module support, expect we're done.
> -    if test ! -e /proc/modules
> -    then
> -        log_success_msg "Kernel has no loadable module support. Skipping modprobe"
> -        return 0
> -    fi
> -
> -    # If openvswitch is already loaded then we're done.
> -    test -e /sys/module/openvswitch && return 0
> -
> -    # Load openvswitch.  If that's successful then we're done.
> -    insert_mods && return 0
> -
> -    # If the bridge module is loaded, then that might be blocking
> -    # openvswitch.  Try to unload it, if there are no bridges.
> -    test -e /sys/module/bridge || return 1
> -    bridges=`echo /sys/class/net/*/bridge | sed 's,/sys/class/net/,,g;s,/bridge,,g'`
> -    if test "$bridges" != "*"; then
> -        log_warning_msg "not removing bridge module because bridges exist ($bridges)"
> -        return 1
> -    fi
> -    action "removing bridge module" rmmod bridge || return 1
> -
> -    # Try loading openvswitch again.
> -    insert_mods
> +    ## This takes care of inserting any required kernel modules
> +    ovs_kmod_ctl insert
>  }
>
>  set_hostname () {
> diff --git a/utilities/ovs-kmod-ctl.8 b/utilities/ovs-kmod-ctl.8
> new file mode 100644
> index 000000000..bc09a8a74
> --- /dev/null
> +++ b/utilities/ovs-kmod-ctl.8
> @@ -0,0 +1,103 @@
> +.\" -*- nroff -*-
> +.de IQ
> +.  br
> +.  ns
> +.  IP "\\$1"
> +..
> +.de ST
> +.  PP
> +.  RS -0.15in
> +.  I "\\$1"
> +.  RE
> +..
> +.TH ovs\-ctl 8 "February 2018" "Open vSwitch" "Open vSwitch Manual"
> +.ds PN ovs\-ctl
> +.
> +.SH NAME
> +ovs\-kmod\-ctl \- OVS startup helper script for loading kernel modules
> +.
> +.SH SYNOPSIS
> +\fBovs\-kmod\-ctl\fR \fBinsert
> +.br
> +\fBovs\-kmod\-ctl \fBremove
> +.br
> +\fBovs\-ctl help \fR| \fB\-h \fR| \fB\-\-help
> +.br
> +\fBovs\-ctl \-\-version

Why ovs-ctl in above lines? Copy paste error?

> +.br
> +\fBovs\-kmod\-ctl version
> +.
> +.SH DESCRIPTION
> +.
> +.PP
> +The \fBovs\-kmod\-ctl\fR program is responsible for inserting and
> +remove Open vSwitch kernel modules.  It is not meant to be invoked
s/remove/removing ?

> +directly by system administrators but to be called internally by
missing comma before but.
> +system startup scripts.


I would add rationale in the man page that this script is used to
leverage SElinux domain transitions. So that admins would not wonder.

> +.
> +.PP
> +Each of \fBovs\-ctl\fR's commands is described separately below.
> +.
> +.SH "The ``insert'' command"
> +.
> +.PP
> +The \fBinsert\fR command loads the Open vSwitch kernel modules, if
> +needed.  If this fails, and the Linux bridge module is loaded but no
> +bridges exist, it tries to unload the bridge module and tries loading
> +the Open vSwitch kernel module again. (This is because the Open
> +vSwitch kernel module cannot coexist with the Linux bridge module
> +before 2.6.37.)
FYI: I believe latest Open vSwitch does not support kernels older than 3.10:

       AC_ERROR([Linux kernel in $KBUILD is version $kversion, but
version 3.10 or later is required])



> +.
> +.SH "The ``remove'' command"
> +.
> +.PP
> +The \fBremove\fR command unloads the Open vSwitch kernel module (including
> +the bridge compatibility module, if loaded) and any associated vport
> +modules.
> +.
> +.SH "EXIT STATUS"
> +.
> +\fBovs\-kmod\-ctl\fR exits with status 0 on success and nonzero on
> +failure.  The \fBinsert\fR command is considered to succeed if kernel
> +modules are already loaded; the \fBremove\fR command is considered to
> +succeed if none of the kernel modules are loaded.
> +.
> +.SH "ENVIRONMENT"
> +.
> +The following environment variables affect \fBovs\-kmod\-ctl\fR:
> +.
> +.IP "\fBPATH\fR"
> +\fBovs\-kmod\-ctl\fR does not hardcode the location of any of the programs
> +that it runs.  \fBovs\-kmod\-ctl\fR will add the \fIsbindir\fR and
> +\fIbindir\fR that were specified at \fBconfigure\fR time to
> +\fBPATH\fR, if they are not already present.
> +.
> +.IP "\fBOVS_LOGDIR\fR"
> +.IQ "\fBOVS_RUNDIR\fR"
> +.IQ "\fBOVS_DBDIR\fR"
> +.IQ "\fBOVS_SYSCONFDIR\fR"
> +.IQ "\fBOVS_PKGDATADIR\fR"
> +.IQ "\fBOVS_BINDIR\fR"
> +.IQ "\fBOVS_SBINDIR\fR"
> +Setting one of these variables in the environment overrides the
> +respective \fBconfigure\fR option, both for \fBovs\-kmod\-ctl\fR itself
> +and for the other Open vSwitch programs that it runs.
> +.
> +.SH "FILES"
> +.
> +\fBovs\-kmod\-ctl\fR uses the following files:
> +.
> +.IP "\fBovs\-lib"
> +Shell function library used internally by \fBovs\-kmod\-ctl\fR.  It must
> +be installed in the same directory as \fBovs\-kmod\-ctl\fR.
> +.
> +.SH "EXAMPLE"
> +.
> +.PP
> +The files \fBdebian/openvswitch\-switch.init\fR and
> +\fBxenserver/etc_init.d_openvswitch\fR in the Open vSwitch source
> +distribution are good examples of how to use \fBovs\-ctl\fR.
> +.
> +.SH "SEE ALSO"
> +.
> +\fBREADME.rst\fR, \fBovs\-ctl\fR(8)
> diff --git a/utilities/ovs-kmod-ctl.in b/utilities/ovs-kmod-ctl.in
> new file mode 100644
> index 000000000..b85f6cd04
> --- /dev/null
> +++ b/utilities/ovs-kmod-ctl.in
> @@ -0,0 +1,228 @@
> +#! /bin/sh
> +# Copyright (C) 2018 Red Hat, Inc.
> +#
> +# Licensed under the Apache License, Version 2.0 (the "License");
> +# you may not use this file except in compliance with the License.
> +# You may obtain a copy of the License at:
> +#
> +#     http://www.apache.org/licenses/LICENSE-2.0
> +#
> +# Unless required by applicable law or agreed to in writing, software
> +# distributed under the License is distributed on an "AS IS" BASIS,
> +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> +# See the License for the specific language governing permissions and
> +# limitations under the License.
> +
> +case $0 in
> +    */*) dir0=`echo "$0" | sed 's,/[^/]*$,,'` ;;
> +    *) dir0=./ ;;
> +esac
> +. "$dir0/ovs-lib" || exit 1
> +
> +for dir in "$sbindir" "$bindir" /sbin /bin /usr/sbin /usr/bin; do
> +    case :$PATH: in
> +        *:$dir:*) ;;
> +        *) PATH=$PATH:$dir ;;
> +    esac
> +done
> +
> +insert_mods () {
> +    # Try loading openvswitch again.
> +    action "Inserting openvswitch module" modprobe openvswitch
> +}
> +
> +insert_kmod_if_required() {
> +    # If this kernel has no module support, expect we're done.
> +    if test ! -e /proc/modules
> +    then
> +        log_success_msg "Kernel has no loadable module support. Skipping modprobe"
> +        return 0
> +    fi
> +
> +    # If openvswitch is already loaded then we're done.
> +    test -e /sys/module/openvswitch && return 0
> +
> +    # Load openvswitch.  If that's successful then we're done.
> +    insert_mods && return 0
> +
> +    # If the bridge module is loaded, then that might be blocking
> +    # openvswitch.  Try to unload it, if there are no bridges.
> +    test -e /sys/module/bridge || return 1
> +    bridges=`echo /sys/class/net/*/bridge | sed 's,/sys/class/net/,,g;s,/bridge,,g'`
> +    if test "$bridges" != "*"; then
> +        log_warning_msg "not removing bridge module because bridges exist ($bridges)"
> +        return 1
> +    fi
> +    action "removing bridge module" rmmod bridge || return 1
> +
> +    # Try loading openvswitch again.
> +    insert_mods
> +}
> +
> +remove_kmods() {
> +    for vport in `awk '/^vport_/ { print $1 }' /proc/modules`; do
> +        action "Removing $vport module" rmmod $vport
> +    done
> +
> +    if test -e /sys/module/openvswitch; then
> +        action "Removing openvswitch module" rmmod openvswitch
> +    fi
> +}
> +
> +set_defaults () {
> +    SYSTEM_ID=
> +
> +    DELETE_BRIDGES=no
> +    DELETE_TRANSIENT_PORTS=no
> +
> +    DAEMON_CWD=/
> +    FORCE_COREFILES=yes
> +    MLOCKALL=yes
> +    SELF_CONFINEMENT=yes
> +    MONITOR=yes
> +    OVS_USER=
> +    OVSDB_SERVER=yes
> +    OVS_VSWITCHD=yes
> +    OVSDB_SERVER_PRIORITY=-10
> +    OVS_VSWITCHD_PRIORITY=-10
> +    OVSDB_SERVER_WRAPPER=
> +    OVS_VSWITCHD_WRAPPER=
> +
> +    DB_FILE=$dbdir/conf.db
> +    DB_SOCK=$rundir/db.sock
> +    DB_SCHEMA=$datadir/vswitch.ovsschema
> +    EXTRA_DBS=
> +
> +    PROTOCOL=gre
> +    DPORT=
> +    SPORT=
> +
> +    type_file=$etcdir/system-type.conf
> +    version_file=$etcdir/system-version.conf
> +
> +    if test -e "$type_file" ; then
> +        SYSTEM_TYPE=`cat $type_file`
> +        SYSTEM_VERSION=`cat $version_file`
> +    elif test -e "@sysconfdir@/os-release"; then
> +        SYSTEM_TYPE=`. '@sysconfdir@/os-release' && echo "$ID"`
> +        SYSTEM_VERSION=`. '@sysconfdir@/os-release' && echo "$VERSION_ID"`
> +    elif (lsb_release --id) >/dev/null 2>&1; then
> +        SYSTEM_TYPE=`lsb_release --id -s`
> +        system_release=`lsb_release --release -s`
> +        system_codename=`lsb_release --codename -s`
> +        SYSTEM_VERSION="${system_release}-${system_codename}"
> +    else
> +        SYSTEM_TYPE=unknown
> +        SYSTEM_VERSION=unknown
> +    fi
> +}
> +
> +usage () {
> +    set_defaults
> +    cat <<EOF
> +$0: controls Open vSwitch kernel modules
> +usage: $0 [OPTIONS] COMMAND
> +
> +This program is intended to be invoked internally by Open vSwitch startup
> +scripts.  System administrators should not normally invoke it directly.
> +
> +Commands:
> +  insert                  insert the Open vSwitch kernel modules
> +  remove                  remove the Open vSwitch kernel modules
> +
> +Options:
> +  -h, --help              display this help message
> +  -V, --version           display version information
> +
> +Default directories with "configure" option and environment variable override:
> +  logs: @LOGDIR@ (--with-logdir, OVS_LOGDIR)
> +  pidfiles and sockets: @RUNDIR@ (--with-rundir, OVS_RUNDIR)
> +  conf.db: @DBDIR@ (--with-dbdir, OVS_DBDIR)
> +  system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
> +  data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
> +  user binaries: @bindir@ (--bindir, OVS_BINDIR)
> +  system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
> +
> +Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
> +EOF
> +
> +    exit 0
> +}
> +
> +set_option () {
> +    var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
> +    eval set=\${$var+yes}
> +    eval old_value=\$$var
> +    if test X$set = X || \
> +        (test $type = bool && \
> +        test X"$old_value" != Xno && test X"$old_value" != Xyes); then
> +        echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
> +        return
> +    fi
> +    eval $var=\$value
> +}
> +
> +set_defaults
> +extra_ids=
> +command=
> +for arg
> +do
> +    case $arg in
> +        -h | --help)
> +            usage
> +            ;;
> +        -V | --version)
> +            echo "$0 (Open vSwitch) $VERSION"
> +            exit 0
> +            ;;
> +        --[a-z]*=*)
> +            option=`expr X"$arg" : 'X--\([^=]*\)'`
> +            value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
> +            type=string
> +            set_option
> +            ;;
> +        --no-[a-z]*)
> +            option=`expr X"$arg" : 'X--no-\(.*\)'`
> +            value=no
> +            type=bool
> +            set_option
> +            ;;
> +        --[a-z]*)
> +            option=`expr X"$arg" : 'X--\(.*\)'`
> +            value=yes
> +            type=bool
> +            set_option
> +            ;;
> +        -*)
> +            echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
> +            exit 1
> +            ;;
> +        *)
> +            if test X"$command" = X; then
> +                command=$arg
> +            else
> +                echo >&2 "$0: exactly one non-option argument required (use --help for help)"
> +                exit 1
> +            fi
> +            ;;
> +    esac
> +done
> +case $command in
> +    remove)
> +        remove_kmods
> +        ;;
> +    insert)
> +        insert_kmod_if_required
> +        ;;
> +    help)
> +        usage
> +        ;;
> +    '')
> +        echo >&2 "$0: missing command name (use --help for help)"
> +        exit 1
> +        ;;
> +    *)
> +        echo >&2 "$0: unknown command \"$command\" (use --help for help)"
> +        exit 1
> +        ;;
> +esac
> diff --git a/utilities/ovs-lib.in b/utilities/ovs-lib.in
> index cf6b6d296..106eaddd9 100644
> --- a/utilities/ovs-lib.in
> +++ b/utilities/ovs-lib.in
> @@ -449,6 +449,10 @@ ovs_vsctl () {
>  ## force-reload-kmod ##
>  ## ----------------- ##
>
> +ovs_kmod_ctl () {
> +    "$dir0/ovs-kmod-ctl" "$@"
> +}
> +
>  internal_interfaces () {
>      # Outputs a list of internal interfaces:
>      #
> @@ -563,13 +567,7 @@ force_reload_kmod () {
>          action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
>      done
>
> -    for vport in `awk '/^vport_/ { print $1 }' /proc/modules`; do
> -        action "Removing $vport module" rmmod $vport
> -    done
> -
> -    if test -e /sys/module/openvswitch; then
> -        action "Removing openvswitch module" rmmod openvswitch
> -    fi
> +    ovs_kmod_ctl remove
>
>      # Start vswitchd by asking it to wait till flow restore is finished.
>      flow_restore_wait
> --
> 2.14.3
>
Aaron Conole March 26, 2018, 9:32 p.m. UTC | #2
Thanks for the review, Ansis!

Ansis Atteka <ansisatteka@gmail.com> writes:

> On 20 March 2018 at 14:05, Aaron Conole <aconole@redhat.com> wrote:
>> Currently, Open vSwitch on linux embeds the logic of loading and unloading
>> kernel modules into the ovs-ctl and ovs-lib script files.  This works, but
>> it means that there is no way to leverage extended filesystem attributes
>> to grant fine grain permissions relating to module loading.
>>
>> The split out utility 'ovs-kmod-ctl' will be used in an upcoming commit
>> for RHEL-based distributions to have a separate transition domain that
>> will allow module loading to be given to a separate selinux domain from
>> the openvswitch_t domain.
>>
>> Signed-off-by: Aaron Conole <aconole@redhat.com>
>> ---
>>  debian/openvswitch-switch.install  |   1 +
>>  debian/openvswitch-switch.manpages |   1 +
>>  rhel/openvswitch-fedora.spec.in    |   2 +
>>  rhel/openvswitch.spec.in           |   2 +
>>  utilities/.gitignore               |   1 +
>>  utilities/automake.mk              |   5 +
>>  utilities/ovs-ctl.in               |  32 +-----
>>  utilities/ovs-kmod-ctl.8           | 103 +++++++++++++++++
>>  utilities/ovs-kmod-ctl.in          | 228 +++++++++++++++++++++++++++++++++++++
>>  utilities/ovs-lib.in               |  12 +-
>>  10 files changed, 350 insertions(+), 37 deletions(-)
>>  create mode 100644 utilities/ovs-kmod-ctl.8
>>  create mode 100644 utilities/ovs-kmod-ctl.in
>>
>> diff --git a/debian/openvswitch-switch.install b/debian/openvswitch-switch.install
>> index bfb391fe8..6a6e9a543 100644
>> --- a/debian/openvswitch-switch.install
>> +++ b/debian/openvswitch-switch.install
>> @@ -12,5 +12,6 @@ usr/sbin/ovs-vswitchd
>>  usr/sbin/ovsdb-server
>>  usr/share/openvswitch/scripts/ovs-check-dead-ifs
>>  usr/share/openvswitch/scripts/ovs-ctl
>> +usr/share/openvswitch/scripts/ovs-kmod-ctl
>>  usr/share/openvswitch/scripts/ovs-save
>>  usr/share/openvswitch/vswitch.ovsschema
>> diff --git a/debian/openvswitch-switch.manpages b/debian/openvswitch-switch.manpages
>> index a2f661a3e..47a1ba174 100644
>> --- a/debian/openvswitch-switch.manpages
>> +++ b/debian/openvswitch-switch.manpages
>> @@ -2,6 +2,7 @@ ovsdb/ovsdb-server.1
>>  utilities/ovs-ctl.8
>>  utilities/ovs-dpctl-top.8
>>  utilities/ovs-dpctl.8
>> +utilities/ovs-kmod-ctl.8
>>  utilities/ovs-pcap.1
>>  utilities/ovs-tcpdump.8
>>  utilities/ovs-tcpundump.1
>> diff --git a/rhel/openvswitch-fedora.spec.in b/rhel/openvswitch-fedora.spec.in
>> index 8a804942b..8fbc985ce 100644
>> --- a/rhel/openvswitch-fedora.spec.in
>> +++ b/rhel/openvswitch-fedora.spec.in
>> @@ -542,6 +542,7 @@ fi
>>  %{_datadir}/openvswitch/scripts/ovs-save
>>  %{_datadir}/openvswitch/scripts/ovs-vtep
>>  %{_datadir}/openvswitch/scripts/ovs-ctl
>> +%{_datadir}/openvswitch/scripts/ovs-kmod-ctl
>>  %{_datadir}/openvswitch/scripts/ovs-systemd-reload
>>  %config %{_datadir}/openvswitch/vswitch.ovsschema
>>  %config %{_datadir}/openvswitch/vtep.ovsschema
>> @@ -574,6 +575,7 @@ fi
>>  %{_mandir}/man8/ovs-ctl.8*
>>  %{_mandir}/man8/ovs-dpctl.8*
>>  %{_mandir}/man8/ovs-dpctl-top.8*
>> +%{_mandir}/man8/ovs-kmod-ctl.8*
>>  %{_mandir}/man8/ovs-ofctl.8*
>>  %{_mandir}/man8/ovs-pki.8*
>>  %{_mandir}/man8/ovs-vsctl.8*
>> diff --git a/rhel/openvswitch.spec.in b/rhel/openvswitch.spec.in
>> index 876990698..71d5afbdb 100644
>> --- a/rhel/openvswitch.spec.in
>> +++ b/rhel/openvswitch.spec.in
>> @@ -236,6 +236,7 @@ exit 0
>>  /usr/share/man/man8/ovs-ctl.8.gz
>>  /usr/share/man/man8/ovs-dpctl.8.gz
>>  /usr/share/man/man8/ovs-dpctl-top.8.gz
>> +/usr/share/man/man8/ovs-kmod-ctl.8.gz
>>  /usr/share/man/man8/ovs-ofctl.8.gz
>>  /usr/share/man/man8/ovs-parse-backtrace.8.gz
>>  /usr/share/man/man8/ovs-pki.8.gz
>> @@ -249,6 +250,7 @@ exit 0
>>  /usr/share/openvswitch/scripts/ovs-bugtool-*
>>  /usr/share/openvswitch/scripts/ovs-check-dead-ifs
>>  /usr/share/openvswitch/scripts/ovs-ctl
>> +/usr/share/openvswitch/scripts/ovs-kmod-ctl
>>  /usr/share/openvswitch/scripts/ovs-lib
>>  /usr/share/openvswitch/scripts/ovs-save
>>  /usr/share/openvswitch/scripts/ovs-vtep
>> diff --git a/utilities/.gitignore b/utilities/.gitignore
>> index 34c58f20f..eb2a69bf3 100644
>> --- a/utilities/.gitignore
>> +++ b/utilities/.gitignore
>> @@ -13,6 +13,7 @@
>>  /ovs-dpctl.8
>>  /ovs-dpctl-top
>>  /ovs-dpctl-top.8
>> +/ovs-kmod-ctl
>>  /ovs-l3ping
>>  /ovs-l3ping.8
>>  /ovs-lib
>> diff --git a/utilities/automake.mk b/utilities/automake.mk
>> index 60cf1c5ed..d8f2374a3 100644
>> --- a/utilities/automake.mk
>> +++ b/utilities/automake.mk
>> @@ -20,6 +20,7 @@ endif
>>  scripts_SCRIPTS += \
>>         utilities/ovs-check-dead-ifs \
>>         utilities/ovs-ctl \
>> +       utilities/ovs-kmod-ctl \
>>         utilities/ovs-save
>>  scripts_DATA += utilities/ovs-lib
>>
>> @@ -44,6 +45,7 @@ EXTRA_DIST += \
>>         utilities/ovs-dev.py \
>>         utilities/ovs-docker \
>>         utilities/ovs-dpctl-top.in \
>> +       utilities/ovs-kmod-ctl.in \
>>         utilities/ovs-l3ping.in \
>>         utilities/ovs-lib.in \
>>         utilities/ovs-parse-backtrace.in \
>> @@ -63,6 +65,7 @@ MAN_ROOTS += \
>>         utilities/ovs-ctl.8 \
>>         utilities/ovs-dpctl.8.in \
>>         utilities/ovs-dpctl-top.8.in \
>> +       utilities/ovs-kmod-ctl.8 \
>>         utilities/ovs-l3ping.8.in \
>>         utilities/ovs-ofctl.8.in \
>>         utilities/ovs-parse-backtrace.8 \
>> @@ -81,6 +84,7 @@ CLEANFILES += \
>>         utilities/ovs-dpctl.8 \
>>         utilities/ovs-dpctl-top \
>>         utilities/ovs-dpctl-top.8 \
>> +       utilities/ovs-kmod-ctl \
>>         utilities/ovs-l3ping \
>>         utilities/ovs-l3ping.8 \
>>         utilities/ovs-lib \
>> @@ -107,6 +111,7 @@ man_MANS += \
>>         utilities/ovs-testcontroller.8 \
>>         utilities/ovs-dpctl.8 \
>>         utilities/ovs-dpctl-top.8 \
>> +       utilities/ovs-kmod-ctl.8 \
>>         utilities/ovs-l3ping.8 \
>>         utilities/ovs-ofctl.8 \
>>         utilities/ovs-parse-backtrace.8 \
>> diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in
>> index ef06dd967..8fdf8909a 100755
>> --- a/utilities/ovs-ctl.in
>> +++ b/utilities/ovs-ctl.in
>> @@ -30,37 +30,9 @@ done
>>  ## start ##
>>  ## ----- ##
>>
>> -insert_mods () {
>> -    # Try loading openvswitch again.
>> -    action "Inserting openvswitch module" modprobe openvswitch
>> -}
>> -
>>  insert_mod_if_required () {
>> -    # If this kernel has no module support, expect we're done.
>> -    if test ! -e /proc/modules
>> -    then
>> -        log_success_msg "Kernel has no loadable module support. Skipping modprobe"
>> -        return 0
>> -    fi
>> -
>> -    # If openvswitch is already loaded then we're done.
>> -    test -e /sys/module/openvswitch && return 0
>> -
>> -    # Load openvswitch.  If that's successful then we're done.
>> -    insert_mods && return 0
>> -
>> -    # If the bridge module is loaded, then that might be blocking
>> -    # openvswitch.  Try to unload it, if there are no bridges.
>> -    test -e /sys/module/bridge || return 1
>> -    bridges=`echo /sys/class/net/*/bridge | sed 's,/sys/class/net/,,g;s,/bridge,,g'`
>> -    if test "$bridges" != "*"; then
>> -        log_warning_msg "not removing bridge module because bridges exist ($bridges)"
>> -        return 1
>> -    fi
>> -    action "removing bridge module" rmmod bridge || return 1
>> -
>> -    # Try loading openvswitch again.
>> -    insert_mods
>> +    ## This takes care of inserting any required kernel modules
>> +    ovs_kmod_ctl insert
>>  }
>>
>>  set_hostname () {
>> diff --git a/utilities/ovs-kmod-ctl.8 b/utilities/ovs-kmod-ctl.8
>> new file mode 100644
>> index 000000000..bc09a8a74
>> --- /dev/null
>> +++ b/utilities/ovs-kmod-ctl.8
>> @@ -0,0 +1,103 @@
>> +.\" -*- nroff -*-
>> +.de IQ
>> +.  br
>> +.  ns
>> +.  IP "\\$1"
>> +..
>> +.de ST
>> +.  PP
>> +.  RS -0.15in
>> +.  I "\\$1"
>> +.  RE
>> +..
>> +.TH ovs\-ctl 8 "February 2018" "Open vSwitch" "Open vSwitch Manual"
>> +.ds PN ovs\-ctl
>> +.
>> +.SH NAME
>> +ovs\-kmod\-ctl \- OVS startup helper script for loading kernel modules
>> +.
>> +.SH SYNOPSIS
>> +\fBovs\-kmod\-ctl\fR \fBinsert
>> +.br
>> +\fBovs\-kmod\-ctl \fBremove
>> +.br
>> +\fBovs\-ctl help \fR| \fB\-h \fR| \fB\-\-help
>> +.br
>> +\fBovs\-ctl \-\-version
>
> Why ovs-ctl in above lines? Copy paste error?

Yep.  Good catch.  Will fix in v2.

>> +.br
>> +\fBovs\-kmod\-ctl version
>> +.
>> +.SH DESCRIPTION
>> +.
>> +.PP
>> +The \fBovs\-kmod\-ctl\fR program is responsible for inserting and
>> +remove Open vSwitch kernel modules.  It is not meant to be invoked
> s/remove/removing ?

Will do.

>> +directly by system administrators but to be called internally by
> missing comma before but.
>> +system startup scripts.
>
>
> I would add rationale in the man page that this script is used to
> leverage SElinux domain transitions. So that admins would not wonder.

Will do.

>> +.
>> +.PP
>> +Each of \fBovs\-ctl\fR's commands is described separately below.
>> +.
>> +.SH "The ``insert'' command"
>> +.
>> +.PP
>> +The \fBinsert\fR command loads the Open vSwitch kernel modules, if
>> +needed.  If this fails, and the Linux bridge module is loaded but no
>> +bridges exist, it tries to unload the bridge module and tries loading
>> +the Open vSwitch kernel module again. (This is because the Open
>> +vSwitch kernel module cannot coexist with the Linux bridge module
>> +before 2.6.37.)
> FYI: I believe latest Open vSwitch does not support kernels older than 3.10:

Sure.  I can take the parenthetical phrase out.

>        AC_ERROR([Linux kernel in $KBUILD is version $kversion, but
> version 3.10 or later is required])
>
>
>
>> +.
>> +.SH "The ``remove'' command"
>> +.
>> +.PP
>> +The \fBremove\fR command unloads the Open vSwitch kernel module (including
>> +the bridge compatibility module, if loaded) and any associated vport
>> +modules.
>> +.
>> +.SH "EXIT STATUS"
>> +.
>> +\fBovs\-kmod\-ctl\fR exits with status 0 on success and nonzero on
>> +failure.  The \fBinsert\fR command is considered to succeed if kernel
>> +modules are already loaded; the \fBremove\fR command is considered to
>> +succeed if none of the kernel modules are loaded.
>> +.
>> +.SH "ENVIRONMENT"
>> +.
>> +The following environment variables affect \fBovs\-kmod\-ctl\fR:
>> +.
>> +.IP "\fBPATH\fR"
>> +\fBovs\-kmod\-ctl\fR does not hardcode the location of any of the programs
>> +that it runs.  \fBovs\-kmod\-ctl\fR will add the \fIsbindir\fR and
>> +\fIbindir\fR that were specified at \fBconfigure\fR time to
>> +\fBPATH\fR, if they are not already present.
>> +.
>> +.IP "\fBOVS_LOGDIR\fR"
>> +.IQ "\fBOVS_RUNDIR\fR"
>> +.IQ "\fBOVS_DBDIR\fR"
>> +.IQ "\fBOVS_SYSCONFDIR\fR"
>> +.IQ "\fBOVS_PKGDATADIR\fR"
>> +.IQ "\fBOVS_BINDIR\fR"
>> +.IQ "\fBOVS_SBINDIR\fR"
>> +Setting one of these variables in the environment overrides the
>> +respective \fBconfigure\fR option, both for \fBovs\-kmod\-ctl\fR itself
>> +and for the other Open vSwitch programs that it runs.
>> +.
>> +.SH "FILES"
>> +.
>> +\fBovs\-kmod\-ctl\fR uses the following files:
>> +.
>> +.IP "\fBovs\-lib"
>> +Shell function library used internally by \fBovs\-kmod\-ctl\fR.  It must
>> +be installed in the same directory as \fBovs\-kmod\-ctl\fR.
>> +.
>> +.SH "EXAMPLE"
>> +.
>> +.PP
>> +The files \fBdebian/openvswitch\-switch.init\fR and
>> +\fBxenserver/etc_init.d_openvswitch\fR in the Open vSwitch source
>> +distribution are good examples of how to use \fBovs\-ctl\fR.
>> +.
>> +.SH "SEE ALSO"
>> +.
>> +\fBREADME.rst\fR, \fBovs\-ctl\fR(8)
>> diff --git a/utilities/ovs-kmod-ctl.in b/utilities/ovs-kmod-ctl.in
>> new file mode 100644
>> index 000000000..b85f6cd04
>> --- /dev/null
>> +++ b/utilities/ovs-kmod-ctl.in
>> @@ -0,0 +1,228 @@
>> +#! /bin/sh
>> +# Copyright (C) 2018 Red Hat, Inc.
>> +#
>> +# Licensed under the Apache License, Version 2.0 (the "License");
>> +# you may not use this file except in compliance with the License.
>> +# You may obtain a copy of the License at:
>> +#
>> +#     http://www.apache.org/licenses/LICENSE-2.0
>> +#
>> +# Unless required by applicable law or agreed to in writing, software
>> +# distributed under the License is distributed on an "AS IS" BASIS,
>> +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>> +# See the License for the specific language governing permissions and
>> +# limitations under the License.
>> +
>> +case $0 in
>> +    */*) dir0=`echo "$0" | sed 's,/[^/]*$,,'` ;;
>> +    *) dir0=./ ;;
>> +esac
>> +. "$dir0/ovs-lib" || exit 1
>> +
>> +for dir in "$sbindir" "$bindir" /sbin /bin /usr/sbin /usr/bin; do
>> +    case :$PATH: in
>> +        *:$dir:*) ;;
>> +        *) PATH=$PATH:$dir ;;
>> +    esac
>> +done
>> +
>> +insert_mods () {
>> +    # Try loading openvswitch again.
>> +    action "Inserting openvswitch module" modprobe openvswitch
>> +}
>> +
>> +insert_kmod_if_required() {
>> +    # If this kernel has no module support, expect we're done.
>> +    if test ! -e /proc/modules
>> +    then
>> +        log_success_msg "Kernel has no loadable module support. Skipping modprobe"
>> +        return 0
>> +    fi
>> +
>> +    # If openvswitch is already loaded then we're done.
>> +    test -e /sys/module/openvswitch && return 0
>> +
>> +    # Load openvswitch.  If that's successful then we're done.
>> +    insert_mods && return 0
>> +
>> +    # If the bridge module is loaded, then that might be blocking
>> +    # openvswitch.  Try to unload it, if there are no bridges.
>> +    test -e /sys/module/bridge || return 1
>> +    bridges=`echo /sys/class/net/*/bridge | sed 's,/sys/class/net/,,g;s,/bridge,,g'`
>> +    if test "$bridges" != "*"; then
>> +        log_warning_msg "not removing bridge module because bridges exist ($bridges)"
>> +        return 1
>> +    fi
>> +    action "removing bridge module" rmmod bridge || return 1
>> +
>> +    # Try loading openvswitch again.
>> +    insert_mods
>> +}
>> +
>> +remove_kmods() {
>> +    for vport in `awk '/^vport_/ { print $1 }' /proc/modules`; do
>> +        action "Removing $vport module" rmmod $vport
>> +    done
>> +
>> +    if test -e /sys/module/openvswitch; then
>> +        action "Removing openvswitch module" rmmod openvswitch
>> +    fi
>> +}
>> +
>> +set_defaults () {
>> +    SYSTEM_ID=
>> +
>> +    DELETE_BRIDGES=no
>> +    DELETE_TRANSIENT_PORTS=no
>> +
>> +    DAEMON_CWD=/
>> +    FORCE_COREFILES=yes
>> +    MLOCKALL=yes
>> +    SELF_CONFINEMENT=yes
>> +    MONITOR=yes
>> +    OVS_USER=
>> +    OVSDB_SERVER=yes
>> +    OVS_VSWITCHD=yes
>> +    OVSDB_SERVER_PRIORITY=-10
>> +    OVS_VSWITCHD_PRIORITY=-10
>> +    OVSDB_SERVER_WRAPPER=
>> +    OVS_VSWITCHD_WRAPPER=
>> +
>> +    DB_FILE=$dbdir/conf.db
>> +    DB_SOCK=$rundir/db.sock
>> +    DB_SCHEMA=$datadir/vswitch.ovsschema
>> +    EXTRA_DBS=
>> +
>> +    PROTOCOL=gre
>> +    DPORT=
>> +    SPORT=
>> +
>> +    type_file=$etcdir/system-type.conf
>> +    version_file=$etcdir/system-version.conf
>> +
>> +    if test -e "$type_file" ; then
>> +        SYSTEM_TYPE=`cat $type_file`
>> +        SYSTEM_VERSION=`cat $version_file`
>> +    elif test -e "@sysconfdir@/os-release"; then
>> +        SYSTEM_TYPE=`. '@sysconfdir@/os-release' && echo "$ID"`
>> +        SYSTEM_VERSION=`. '@sysconfdir@/os-release' && echo "$VERSION_ID"`
>> +    elif (lsb_release --id) >/dev/null 2>&1; then
>> +        SYSTEM_TYPE=`lsb_release --id -s`
>> +        system_release=`lsb_release --release -s`
>> +        system_codename=`lsb_release --codename -s`
>> +        SYSTEM_VERSION="${system_release}-${system_codename}"
>> +    else
>> +        SYSTEM_TYPE=unknown
>> +        SYSTEM_VERSION=unknown
>> +    fi
>> +}
>> +
>> +usage () {
>> +    set_defaults
>> +    cat <<EOF
>> +$0: controls Open vSwitch kernel modules
>> +usage: $0 [OPTIONS] COMMAND
>> +
>> +This program is intended to be invoked internally by Open vSwitch startup
>> +scripts.  System administrators should not normally invoke it directly.
>> +
>> +Commands:
>> +  insert                  insert the Open vSwitch kernel modules
>> +  remove                  remove the Open vSwitch kernel modules
>> +
>> +Options:
>> +  -h, --help              display this help message
>> +  -V, --version           display version information
>> +
>> +Default directories with "configure" option and environment variable override:
>> +  logs: @LOGDIR@ (--with-logdir, OVS_LOGDIR)
>> +  pidfiles and sockets: @RUNDIR@ (--with-rundir, OVS_RUNDIR)
>> +  conf.db: @DBDIR@ (--with-dbdir, OVS_DBDIR)
>> +  system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
>> +  data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
>> +  user binaries: @bindir@ (--bindir, OVS_BINDIR)
>> +  system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
>> +
>> +Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
>> +EOF
>> +
>> +    exit 0
>> +}
>> +
>> +set_option () {
>> +    var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
>> +    eval set=\${$var+yes}
>> +    eval old_value=\$$var
>> +    if test X$set = X || \
>> +        (test $type = bool && \
>> +        test X"$old_value" != Xno && test X"$old_value" != Xyes); then
>> +        echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
>> +        return
>> +    fi
>> +    eval $var=\$value
>> +}
>> +
>> +set_defaults
>> +extra_ids=
>> +command=
>> +for arg
>> +do
>> +    case $arg in
>> +        -h | --help)
>> +            usage
>> +            ;;
>> +        -V | --version)
>> +            echo "$0 (Open vSwitch) $VERSION"
>> +            exit 0
>> +            ;;
>> +        --[a-z]*=*)
>> +            option=`expr X"$arg" : 'X--\([^=]*\)'`
>> +            value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
>> +            type=string
>> +            set_option
>> +            ;;
>> +        --no-[a-z]*)
>> +            option=`expr X"$arg" : 'X--no-\(.*\)'`
>> +            value=no
>> +            type=bool
>> +            set_option
>> +            ;;
>> +        --[a-z]*)
>> +            option=`expr X"$arg" : 'X--\(.*\)'`
>> +            value=yes
>> +            type=bool
>> +            set_option
>> +            ;;
>> +        -*)
>> +            echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
>> +            exit 1
>> +            ;;
>> +        *)
>> +            if test X"$command" = X; then
>> +                command=$arg
>> +            else
>> +                echo >&2 "$0: exactly one non-option argument required (use --help for help)"
>> +                exit 1
>> +            fi
>> +            ;;
>> +    esac
>> +done
>> +case $command in
>> +    remove)
>> +        remove_kmods
>> +        ;;
>> +    insert)
>> +        insert_kmod_if_required
>> +        ;;
>> +    help)
>> +        usage
>> +        ;;
>> +    '')
>> +        echo >&2 "$0: missing command name (use --help for help)"
>> +        exit 1
>> +        ;;
>> +    *)
>> +        echo >&2 "$0: unknown command \"$command\" (use --help for help)"
>> +        exit 1
>> +        ;;
>> +esac
>> diff --git a/utilities/ovs-lib.in b/utilities/ovs-lib.in
>> index cf6b6d296..106eaddd9 100644
>> --- a/utilities/ovs-lib.in
>> +++ b/utilities/ovs-lib.in
>> @@ -449,6 +449,10 @@ ovs_vsctl () {
>>  ## force-reload-kmod ##
>>  ## ----------------- ##
>>
>> +ovs_kmod_ctl () {
>> +    "$dir0/ovs-kmod-ctl" "$@"
>> +}
>> +
>>  internal_interfaces () {
>>      # Outputs a list of internal interfaces:
>>      #
>> @@ -563,13 +567,7 @@ force_reload_kmod () {
>>          action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
>>      done
>>
>> -    for vport in `awk '/^vport_/ { print $1 }' /proc/modules`; do
>> -        action "Removing $vport module" rmmod $vport
>> -    done
>> -
>> -    if test -e /sys/module/openvswitch; then
>> -        action "Removing openvswitch module" rmmod openvswitch
>> -    fi
>> +    ovs_kmod_ctl remove
>>
>>      # Start vswitchd by asking it to wait till flow restore is finished.
>>      flow_restore_wait
>> --
>> 2.14.3
>>
Joe Stringer March 27, 2018, 2:58 a.m. UTC | #3
On 26 March 2018 at 14:32, Aaron Conole <aconole@redhat.com> wrote:
> Thanks for the review, Ansis!
>
> Ansis Atteka <ansisatteka@gmail.com> writes:
>
>> On 20 March 2018 at 14:05, Aaron Conole <aconole@redhat.com> wrote:
>>> +.
>>> +.PP
>>> +Each of \fBovs\-ctl\fR's commands is described separately below.
>>> +.
>>> +.SH "The ``insert'' command"
>>> +.
>>> +.PP
>>> +The \fBinsert\fR command loads the Open vSwitch kernel modules, if
>>> +needed.  If this fails, and the Linux bridge module is loaded but no
>>> +bridges exist, it tries to unload the bridge module and tries loading
>>> +the Open vSwitch kernel module again. (This is because the Open
>>> +vSwitch kernel module cannot coexist with the Linux bridge module
>>> +before 2.6.37.)
>> FYI: I believe latest Open vSwitch does not support kernels older than 3.10:
>
> Sure.  I can take the parenthetical phrase out.
>
>>        AC_ERROR([Linux kernel in $KBUILD is version $kversion, but
>> version 3.10 or later is required])

FWIW this isn't supported kernel versions, this is only versions that
the module in the tree will compile against. In theory people can
still use older kernels with the latest OVS userspace (though some
features may be missing).
Ansis Atteka March 27, 2018, 4:39 a.m. UTC | #4
On 26 March 2018 at 19:58, Joe Stringer <joe@ovn.org> wrote:
> On 26 March 2018 at 14:32, Aaron Conole <aconole@redhat.com> wrote:
>> Thanks for the review, Ansis!
>>
>> Ansis Atteka <ansisatteka@gmail.com> writes:
>>
>>> On 20 March 2018 at 14:05, Aaron Conole <aconole@redhat.com> wrote:
>>>> +.
>>>> +.PP
>>>> +Each of \fBovs\-ctl\fR's commands is described separately below.
>>>> +.
>>>> +.SH "The ``insert'' command"
>>>> +.
>>>> +.PP
>>>> +The \fBinsert\fR command loads the Open vSwitch kernel modules, if
>>>> +needed.  If this fails, and the Linux bridge module is loaded but no
>>>> +bridges exist, it tries to unload the bridge module and tries loading
>>>> +the Open vSwitch kernel module again. (This is because the Open
>>>> +vSwitch kernel module cannot coexist with the Linux bridge module
>>>> +before 2.6.37.)
>>> FYI: I believe latest Open vSwitch does not support kernels older than 3.10:
>>
>> Sure.  I can take the parenthetical phrase out.
>>
>>>        AC_ERROR([Linux kernel in $KBUILD is version $kversion, but
>>> version 3.10 or later is required])
>
> FWIW this isn't supported kernel versions, this is only versions that
> the module in the tree will compile against. In theory people can
> still use older kernels with the latest OVS userspace (though some
> features may be missing).
You are right. Thanks for correcting.

Patch
diff mbox series

diff --git a/debian/openvswitch-switch.install b/debian/openvswitch-switch.install
index bfb391fe8..6a6e9a543 100644
--- a/debian/openvswitch-switch.install
+++ b/debian/openvswitch-switch.install
@@ -12,5 +12,6 @@  usr/sbin/ovs-vswitchd
 usr/sbin/ovsdb-server
 usr/share/openvswitch/scripts/ovs-check-dead-ifs
 usr/share/openvswitch/scripts/ovs-ctl
+usr/share/openvswitch/scripts/ovs-kmod-ctl
 usr/share/openvswitch/scripts/ovs-save
 usr/share/openvswitch/vswitch.ovsschema
diff --git a/debian/openvswitch-switch.manpages b/debian/openvswitch-switch.manpages
index a2f661a3e..47a1ba174 100644
--- a/debian/openvswitch-switch.manpages
+++ b/debian/openvswitch-switch.manpages
@@ -2,6 +2,7 @@  ovsdb/ovsdb-server.1
 utilities/ovs-ctl.8
 utilities/ovs-dpctl-top.8
 utilities/ovs-dpctl.8
+utilities/ovs-kmod-ctl.8
 utilities/ovs-pcap.1
 utilities/ovs-tcpdump.8
 utilities/ovs-tcpundump.1
diff --git a/rhel/openvswitch-fedora.spec.in b/rhel/openvswitch-fedora.spec.in
index 8a804942b..8fbc985ce 100644
--- a/rhel/openvswitch-fedora.spec.in
+++ b/rhel/openvswitch-fedora.spec.in
@@ -542,6 +542,7 @@  fi
 %{_datadir}/openvswitch/scripts/ovs-save
 %{_datadir}/openvswitch/scripts/ovs-vtep
 %{_datadir}/openvswitch/scripts/ovs-ctl
+%{_datadir}/openvswitch/scripts/ovs-kmod-ctl
 %{_datadir}/openvswitch/scripts/ovs-systemd-reload
 %config %{_datadir}/openvswitch/vswitch.ovsschema
 %config %{_datadir}/openvswitch/vtep.ovsschema
@@ -574,6 +575,7 @@  fi
 %{_mandir}/man8/ovs-ctl.8*
 %{_mandir}/man8/ovs-dpctl.8*
 %{_mandir}/man8/ovs-dpctl-top.8*
+%{_mandir}/man8/ovs-kmod-ctl.8*
 %{_mandir}/man8/ovs-ofctl.8*
 %{_mandir}/man8/ovs-pki.8*
 %{_mandir}/man8/ovs-vsctl.8*
diff --git a/rhel/openvswitch.spec.in b/rhel/openvswitch.spec.in
index 876990698..71d5afbdb 100644
--- a/rhel/openvswitch.spec.in
+++ b/rhel/openvswitch.spec.in
@@ -236,6 +236,7 @@  exit 0
 /usr/share/man/man8/ovs-ctl.8.gz
 /usr/share/man/man8/ovs-dpctl.8.gz
 /usr/share/man/man8/ovs-dpctl-top.8.gz
+/usr/share/man/man8/ovs-kmod-ctl.8.gz
 /usr/share/man/man8/ovs-ofctl.8.gz
 /usr/share/man/man8/ovs-parse-backtrace.8.gz
 /usr/share/man/man8/ovs-pki.8.gz
@@ -249,6 +250,7 @@  exit 0
 /usr/share/openvswitch/scripts/ovs-bugtool-*
 /usr/share/openvswitch/scripts/ovs-check-dead-ifs
 /usr/share/openvswitch/scripts/ovs-ctl
+/usr/share/openvswitch/scripts/ovs-kmod-ctl
 /usr/share/openvswitch/scripts/ovs-lib
 /usr/share/openvswitch/scripts/ovs-save
 /usr/share/openvswitch/scripts/ovs-vtep
diff --git a/utilities/.gitignore b/utilities/.gitignore
index 34c58f20f..eb2a69bf3 100644
--- a/utilities/.gitignore
+++ b/utilities/.gitignore
@@ -13,6 +13,7 @@ 
 /ovs-dpctl.8
 /ovs-dpctl-top
 /ovs-dpctl-top.8
+/ovs-kmod-ctl
 /ovs-l3ping
 /ovs-l3ping.8
 /ovs-lib
diff --git a/utilities/automake.mk b/utilities/automake.mk
index 60cf1c5ed..d8f2374a3 100644
--- a/utilities/automake.mk
+++ b/utilities/automake.mk
@@ -20,6 +20,7 @@  endif
 scripts_SCRIPTS += \
 	utilities/ovs-check-dead-ifs \
 	utilities/ovs-ctl \
+	utilities/ovs-kmod-ctl \
 	utilities/ovs-save
 scripts_DATA += utilities/ovs-lib
 
@@ -44,6 +45,7 @@  EXTRA_DIST += \
 	utilities/ovs-dev.py \
 	utilities/ovs-docker \
 	utilities/ovs-dpctl-top.in \
+	utilities/ovs-kmod-ctl.in \
 	utilities/ovs-l3ping.in \
 	utilities/ovs-lib.in \
 	utilities/ovs-parse-backtrace.in \
@@ -63,6 +65,7 @@  MAN_ROOTS += \
 	utilities/ovs-ctl.8 \
 	utilities/ovs-dpctl.8.in \
 	utilities/ovs-dpctl-top.8.in \
+	utilities/ovs-kmod-ctl.8 \
 	utilities/ovs-l3ping.8.in \
 	utilities/ovs-ofctl.8.in \
 	utilities/ovs-parse-backtrace.8 \
@@ -81,6 +84,7 @@  CLEANFILES += \
 	utilities/ovs-dpctl.8 \
 	utilities/ovs-dpctl-top \
 	utilities/ovs-dpctl-top.8 \
+	utilities/ovs-kmod-ctl \
 	utilities/ovs-l3ping \
 	utilities/ovs-l3ping.8 \
 	utilities/ovs-lib \
@@ -107,6 +111,7 @@  man_MANS += \
 	utilities/ovs-testcontroller.8 \
 	utilities/ovs-dpctl.8 \
 	utilities/ovs-dpctl-top.8 \
+	utilities/ovs-kmod-ctl.8 \
 	utilities/ovs-l3ping.8 \
 	utilities/ovs-ofctl.8 \
 	utilities/ovs-parse-backtrace.8 \
diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in
index ef06dd967..8fdf8909a 100755
--- a/utilities/ovs-ctl.in
+++ b/utilities/ovs-ctl.in
@@ -30,37 +30,9 @@  done
 ## start ##
 ## ----- ##
 
-insert_mods () {
-    # Try loading openvswitch again.
-    action "Inserting openvswitch module" modprobe openvswitch
-}
-
 insert_mod_if_required () {
-    # If this kernel has no module support, expect we're done.
-    if test ! -e /proc/modules
-    then
-        log_success_msg "Kernel has no loadable module support. Skipping modprobe"
-        return 0
-    fi
-
-    # If openvswitch is already loaded then we're done.
-    test -e /sys/module/openvswitch && return 0
-
-    # Load openvswitch.  If that's successful then we're done.
-    insert_mods && return 0
-
-    # If the bridge module is loaded, then that might be blocking
-    # openvswitch.  Try to unload it, if there are no bridges.
-    test -e /sys/module/bridge || return 1
-    bridges=`echo /sys/class/net/*/bridge | sed 's,/sys/class/net/,,g;s,/bridge,,g'`
-    if test "$bridges" != "*"; then
-        log_warning_msg "not removing bridge module because bridges exist ($bridges)"
-        return 1
-    fi
-    action "removing bridge module" rmmod bridge || return 1
-
-    # Try loading openvswitch again.
-    insert_mods
+    ## This takes care of inserting any required kernel modules
+    ovs_kmod_ctl insert
 }
 
 set_hostname () {
diff --git a/utilities/ovs-kmod-ctl.8 b/utilities/ovs-kmod-ctl.8
new file mode 100644
index 000000000..bc09a8a74
--- /dev/null
+++ b/utilities/ovs-kmod-ctl.8
@@ -0,0 +1,103 @@ 
+.\" -*- nroff -*-
+.de IQ
+.  br
+.  ns
+.  IP "\\$1"
+..
+.de ST
+.  PP
+.  RS -0.15in
+.  I "\\$1"
+.  RE
+..
+.TH ovs\-ctl 8 "February 2018" "Open vSwitch" "Open vSwitch Manual"
+.ds PN ovs\-ctl
+.
+.SH NAME
+ovs\-kmod\-ctl \- OVS startup helper script for loading kernel modules
+.
+.SH SYNOPSIS
+\fBovs\-kmod\-ctl\fR \fBinsert
+.br
+\fBovs\-kmod\-ctl \fBremove
+.br
+\fBovs\-ctl help \fR| \fB\-h \fR| \fB\-\-help
+.br
+\fBovs\-ctl \-\-version
+.br
+\fBovs\-kmod\-ctl version
+.
+.SH DESCRIPTION
+.
+.PP
+The \fBovs\-kmod\-ctl\fR program is responsible for inserting and
+remove Open vSwitch kernel modules.  It is not meant to be invoked
+directly by system administrators but to be called internally by
+system startup scripts.
+.
+.PP
+Each of \fBovs\-ctl\fR's commands is described separately below.
+.
+.SH "The ``insert'' command"
+.
+.PP
+The \fBinsert\fR command loads the Open vSwitch kernel modules, if
+needed.  If this fails, and the Linux bridge module is loaded but no
+bridges exist, it tries to unload the bridge module and tries loading
+the Open vSwitch kernel module again. (This is because the Open
+vSwitch kernel module cannot coexist with the Linux bridge module
+before 2.6.37.)
+.
+.SH "The ``remove'' command"
+.
+.PP
+The \fBremove\fR command unloads the Open vSwitch kernel module (including
+the bridge compatibility module, if loaded) and any associated vport
+modules.
+.
+.SH "EXIT STATUS"
+.
+\fBovs\-kmod\-ctl\fR exits with status 0 on success and nonzero on
+failure.  The \fBinsert\fR command is considered to succeed if kernel
+modules are already loaded; the \fBremove\fR command is considered to
+succeed if none of the kernel modules are loaded.
+.
+.SH "ENVIRONMENT"
+.
+The following environment variables affect \fBovs\-kmod\-ctl\fR:
+.
+.IP "\fBPATH\fR"
+\fBovs\-kmod\-ctl\fR does not hardcode the location of any of the programs
+that it runs.  \fBovs\-kmod\-ctl\fR will add the \fIsbindir\fR and
+\fIbindir\fR that were specified at \fBconfigure\fR time to
+\fBPATH\fR, if they are not already present.
+.
+.IP "\fBOVS_LOGDIR\fR"
+.IQ "\fBOVS_RUNDIR\fR"
+.IQ "\fBOVS_DBDIR\fR"
+.IQ "\fBOVS_SYSCONFDIR\fR"
+.IQ "\fBOVS_PKGDATADIR\fR"
+.IQ "\fBOVS_BINDIR\fR"
+.IQ "\fBOVS_SBINDIR\fR"
+Setting one of these variables in the environment overrides the
+respective \fBconfigure\fR option, both for \fBovs\-kmod\-ctl\fR itself
+and for the other Open vSwitch programs that it runs.
+.
+.SH "FILES"
+.
+\fBovs\-kmod\-ctl\fR uses the following files:
+.
+.IP "\fBovs\-lib"
+Shell function library used internally by \fBovs\-kmod\-ctl\fR.  It must
+be installed in the same directory as \fBovs\-kmod\-ctl\fR.
+.
+.SH "EXAMPLE"
+.
+.PP
+The files \fBdebian/openvswitch\-switch.init\fR and
+\fBxenserver/etc_init.d_openvswitch\fR in the Open vSwitch source
+distribution are good examples of how to use \fBovs\-ctl\fR.
+.
+.SH "SEE ALSO"
+.
+\fBREADME.rst\fR, \fBovs\-ctl\fR(8)
diff --git a/utilities/ovs-kmod-ctl.in b/utilities/ovs-kmod-ctl.in
new file mode 100644
index 000000000..b85f6cd04
--- /dev/null
+++ b/utilities/ovs-kmod-ctl.in
@@ -0,0 +1,228 @@ 
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+case $0 in
+    */*) dir0=`echo "$0" | sed 's,/[^/]*$,,'` ;;
+    *) dir0=./ ;;
+esac
+. "$dir0/ovs-lib" || exit 1
+
+for dir in "$sbindir" "$bindir" /sbin /bin /usr/sbin /usr/bin; do
+    case :$PATH: in
+        *:$dir:*) ;;
+        *) PATH=$PATH:$dir ;;
+    esac
+done
+
+insert_mods () {
+    # Try loading openvswitch again.
+    action "Inserting openvswitch module" modprobe openvswitch
+}
+
+insert_kmod_if_required() {
+    # If this kernel has no module support, expect we're done.
+    if test ! -e /proc/modules
+    then
+        log_success_msg "Kernel has no loadable module support. Skipping modprobe"
+        return 0
+    fi
+
+    # If openvswitch is already loaded then we're done.
+    test -e /sys/module/openvswitch && return 0
+
+    # Load openvswitch.  If that's successful then we're done.
+    insert_mods && return 0
+
+    # If the bridge module is loaded, then that might be blocking
+    # openvswitch.  Try to unload it, if there are no bridges.
+    test -e /sys/module/bridge || return 1
+    bridges=`echo /sys/class/net/*/bridge | sed 's,/sys/class/net/,,g;s,/bridge,,g'`
+    if test "$bridges" != "*"; then
+        log_warning_msg "not removing bridge module because bridges exist ($bridges)"
+        return 1
+    fi
+    action "removing bridge module" rmmod bridge || return 1
+
+    # Try loading openvswitch again.
+    insert_mods
+}
+
+remove_kmods() {
+    for vport in `awk '/^vport_/ { print $1 }' /proc/modules`; do
+        action "Removing $vport module" rmmod $vport
+    done
+
+    if test -e /sys/module/openvswitch; then
+        action "Removing openvswitch module" rmmod openvswitch
+    fi
+}
+
+set_defaults () {
+    SYSTEM_ID=
+
+    DELETE_BRIDGES=no
+    DELETE_TRANSIENT_PORTS=no
+
+    DAEMON_CWD=/
+    FORCE_COREFILES=yes
+    MLOCKALL=yes
+    SELF_CONFINEMENT=yes
+    MONITOR=yes
+    OVS_USER=
+    OVSDB_SERVER=yes
+    OVS_VSWITCHD=yes
+    OVSDB_SERVER_PRIORITY=-10
+    OVS_VSWITCHD_PRIORITY=-10
+    OVSDB_SERVER_WRAPPER=
+    OVS_VSWITCHD_WRAPPER=
+
+    DB_FILE=$dbdir/conf.db
+    DB_SOCK=$rundir/db.sock
+    DB_SCHEMA=$datadir/vswitch.ovsschema
+    EXTRA_DBS=
+
+    PROTOCOL=gre
+    DPORT=
+    SPORT=
+
+    type_file=$etcdir/system-type.conf
+    version_file=$etcdir/system-version.conf
+
+    if test -e "$type_file" ; then
+        SYSTEM_TYPE=`cat $type_file`
+        SYSTEM_VERSION=`cat $version_file`
+    elif test -e "@sysconfdir@/os-release"; then
+        SYSTEM_TYPE=`. '@sysconfdir@/os-release' && echo "$ID"`
+        SYSTEM_VERSION=`. '@sysconfdir@/os-release' && echo "$VERSION_ID"`
+    elif (lsb_release --id) >/dev/null 2>&1; then
+        SYSTEM_TYPE=`lsb_release --id -s`
+        system_release=`lsb_release --release -s`
+        system_codename=`lsb_release --codename -s`
+        SYSTEM_VERSION="${system_release}-${system_codename}"
+    else
+        SYSTEM_TYPE=unknown
+        SYSTEM_VERSION=unknown
+    fi
+}
+
+usage () {
+    set_defaults
+    cat <<EOF
+$0: controls Open vSwitch kernel modules
+usage: $0 [OPTIONS] COMMAND
+
+This program is intended to be invoked internally by Open vSwitch startup
+scripts.  System administrators should not normally invoke it directly.
+
+Commands:
+  insert                  insert the Open vSwitch kernel modules
+  remove                  remove the Open vSwitch kernel modules
+
+Options:
+  -h, --help              display this help message
+  -V, --version           display version information
+
+Default directories with "configure" option and environment variable override:
+  logs: @LOGDIR@ (--with-logdir, OVS_LOGDIR)
+  pidfiles and sockets: @RUNDIR@ (--with-rundir, OVS_RUNDIR)
+  conf.db: @DBDIR@ (--with-dbdir, OVS_DBDIR)
+  system configuration: @sysconfdir@ (--sysconfdir, OVS_SYSCONFDIR)
+  data files: @pkgdatadir@ (--pkgdatadir, OVS_PKGDATADIR)
+  user binaries: @bindir@ (--bindir, OVS_BINDIR)
+  system binaries: @sbindir@ (--sbindir, OVS_SBINDIR)
+
+Please report bugs to bugs@openvswitch.org (see REPORTING-BUGS for details).
+EOF
+
+    exit 0
+}
+
+set_option () {
+    var=`echo "$option" | tr abcdefghijklmnopqrstuvwxyz- ABCDEFGHIJKLMNOPQRSTUVWXYZ_`
+    eval set=\${$var+yes}
+    eval old_value=\$$var
+    if test X$set = X || \
+        (test $type = bool && \
+        test X"$old_value" != Xno && test X"$old_value" != Xyes); then
+        echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
+        return
+    fi
+    eval $var=\$value
+}
+
+set_defaults
+extra_ids=
+command=
+for arg
+do
+    case $arg in
+        -h | --help)
+            usage
+            ;;
+        -V | --version)
+            echo "$0 (Open vSwitch) $VERSION"
+            exit 0
+            ;;
+        --[a-z]*=*)
+            option=`expr X"$arg" : 'X--\([^=]*\)'`
+            value=`expr X"$arg" : 'X[^=]*=\(.*\)'`
+            type=string
+            set_option
+            ;;
+        --no-[a-z]*)
+            option=`expr X"$arg" : 'X--no-\(.*\)'`
+            value=no
+            type=bool
+            set_option
+            ;;
+        --[a-z]*)
+            option=`expr X"$arg" : 'X--\(.*\)'`
+            value=yes
+            type=bool
+            set_option
+            ;;
+        -*)
+            echo >&2 "$0: unknown option \"$arg\" (use --help for help)"
+            exit 1
+            ;;
+        *)
+            if test X"$command" = X; then
+                command=$arg
+            else
+                echo >&2 "$0: exactly one non-option argument required (use --help for help)"
+                exit 1
+            fi
+            ;;
+    esac
+done
+case $command in
+    remove)
+        remove_kmods
+        ;;
+    insert)
+        insert_kmod_if_required
+        ;;
+    help)
+        usage
+        ;;
+    '')
+        echo >&2 "$0: missing command name (use --help for help)"
+        exit 1
+        ;;
+    *)
+        echo >&2 "$0: unknown command \"$command\" (use --help for help)"
+        exit 1
+        ;;
+esac
diff --git a/utilities/ovs-lib.in b/utilities/ovs-lib.in
index cf6b6d296..106eaddd9 100644
--- a/utilities/ovs-lib.in
+++ b/utilities/ovs-lib.in
@@ -449,6 +449,10 @@  ovs_vsctl () {
 ## force-reload-kmod ##
 ## ----------------- ##
 
+ovs_kmod_ctl () {
+    "$dir0/ovs-kmod-ctl" "$@"
+}
+
 internal_interfaces () {
     # Outputs a list of internal interfaces:
     #
@@ -563,13 +567,7 @@  force_reload_kmod () {
         action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
     done
 
-    for vport in `awk '/^vport_/ { print $1 }' /proc/modules`; do
-        action "Removing $vport module" rmmod $vport
-    done
-
-    if test -e /sys/module/openvswitch; then
-        action "Removing openvswitch module" rmmod openvswitch
-    fi
+    ovs_kmod_ctl remove
 
     # Start vswitchd by asking it to wait till flow restore is finished.
     flow_restore_wait