[ovs-dev] [PATCH v3] ovs-ctl.in: Ability to save flows and kernel datapath config.

Gurucharan Shetty gshetty at nicira.com
Tue Oct 23 21:16:25 UTC 2012


On Tue, Oct 23, 2012 at 12:01 PM, Gurucharan Shetty <gshetty at nicira.com>wrote:

> Add a new command - "restart" to ovs-ctl. Calling this command
> will save and restore the Openflow flows on each bridge while
> stopping and starting the userspace daemons respectively.
>
> Also, during a force-reload-kmod, save the flows and kernel datapath
> configuration. Use the saved datapath configuration while readding
> the kernel module and the flows while starting the userspace daemons.
>
> Feature #13555.
> Signed-off-by: Gurucharan Shetty <gshetty at nicira.com>
> ---
>  utilities/ovs-ctl.8  |   29 +++--
>  utilities/ovs-ctl.in |  102 +++++++++++++--
>  utilities/ovs-save   |  334
> ++++++++++++++++++++++++++++++++++----------------
>  3 files changed, 337 insertions(+), 128 deletions(-)
>
> diff --git a/utilities/ovs-ctl.8 b/utilities/ovs-ctl.8
> index 8cbd3cf..3092d46 100644
> --- a/utilities/ovs-ctl.8
> +++ b/utilities/ovs-ctl.8
> @@ -250,6 +250,14 @@ modules.
>  This command does nothing and finishes successfully if the OVS daemons
>  aren't running.
>  .
> +.SH "The ``restart'' command"
> +.
> +.PP
> +The \fBrestart\fR command performs a \fBstop\fR followed by a \fBstart\fR
> +command.  The command can take the same options as that of the \fBstart\fR
> +command. In addition, it saves and restores Openflow flows for each
> +individual bridge.
> +.
>  .SH "The ``status'' command"
>  .
>  .PP
> @@ -279,27 +287,32 @@ implemented by Open vSwitch.  The most common
> examples of these are
>  bridge ``local ports''.
>  .
>  .IP 2.
> +Saves the Openflow flows of each bridge and the kernel datapath
> +configuration for each of the kernel datapaths.
> +.
> +.IP 3.
>  Stops the Open vSwitch daemons, as if by a call to \fBovs\-ctl
>  stop\fR.
>  .
> -.IP 3.
> +.IP 4.
>  Saves the kernel configuration state of the OVS internal interfaces
>  listed in step 1, including IP and IPv6 addresses and routing table
>  entries.
>  .
> -.IP 4.
> +.IP 5.
>  Unloads the Open vSwitch kernel module (including the bridge
>  compatibility module if it is loaded).
>  .
> -.IP 5.
> -Starts OVS back up, as if by a call to \fBovs\-ctl start\fR.  This
> -reloads the kernel module and restarts the OVS daemons (including
> -\fBovs\-brcompatd\fR, if \fB\-\-brcompat\fR is specified).
> -.
>  .IP 6.
> -Restores the kernel configuration state that was saved in step 3.
> +Starts OVS back up, as if by a call to \fBovs\-ctl start\fR.  This
> +reloads the kernel module, restores the saved kernel datapath
> configuration,
> +restarts the OVS daemons (including \fBovs\-brcompatd\fR, if
> \fB\-\-brcompat\fR
> +is specified) and finally restores the saved Openflow flows.
>  .
>  .IP 7.
> +Restores the kernel configuration state that was saved in step 4.
> +.
> +.IP 8.
>  Checks for daemons that may need to be restarted because they have
>  packet sockets that are listening on old instances of Open vSwitch
>  kernel interfaces and, if it finds any, prints a warning on stdout.
> diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in
> index 2ead004..4b63f62 100755
> --- a/utilities/ovs-ctl.in
> +++ b/utilities/ovs-ctl.in
> @@ -30,13 +30,21 @@ done
>  ## start ##
>  ## ----- ##
>
> +restore_datapaths () {
> +    [ -n "${script_datapaths}" ] && \
> +        action "Restoring datapath configuration" "${script_datapaths}"
> +}
> +
>  insert_openvswitch_mod_if_required () {
>      # If openvswitch is already loaded then we're done.
>      test -e /sys/module/openvswitch -o -e /sys/module/openvswitch_mod && \
>       return 0
>
>      # Load openvswitch.  If that's successful then we're done.
> -    action "Inserting openvswitch module" modprobe openvswitch && return 0
> +    if action "Inserting openvswitch module" modprobe openvswitch; then
> +        restore_datapaths
> +        return 0
> +    fi
>
>      # If the bridge module is loaded, then that might be blocking
>      # openvswitch.  Try to unload it, if there are no bridges.
> @@ -50,6 +58,7 @@ insert_openvswitch_mod_if_required () {
>
>      # Try loading openvswitch again.
>      action "Inserting openvswitch module" modprobe openvswitch
> +    restore_datapaths
>  }
>
>  insert_brcompat_mod_if_required () {
> @@ -293,14 +302,46 @@ internal_interfaces () {
>      done
>  }
>
> +save_flows () {
> +   if set X `ovs_vsctl list-br`; then
> +        shift
> +        if "$datadir/scripts/ovs-save" save-flows "$@" > "$script_flows";
> then
> +            chmod +x "$script_flows"
> +            return 0
> +        fi
> +    fi
> +    script_flows=
> +    log_warning_msg "Failed to save flows."
> +    return 1
> +}
> +
>  save_interfaces () {
> -    "$datadir/scripts/ovs-save" $ifaces > "$script"
> +    "$datadir/scripts/ovs-save" save-interfaces ${ifaces} \
> +        > "${script_interfaces}"
> +}
> +
> +save_datapaths () {
> +    "$datadir/scripts/ovs-save" save-datapaths ${datapaths} \
> +        > "${script_datapaths}"
> +}
> +
> +restore_flows () {
> +    [ -n "${script_flows}" ] && \
> +        action "Restoring saved flows" "${script_flows}"
>  }
>
>  force_reload_kmod () {
>      ifaces=`internal_interfaces`
>      action "Detected internal interfaces: $ifaces" true
>
> +    script_interfaces=`mktemp`
> +    script_datapaths=`mktemp`
> +    script_flows=`mktemp`
> +    trap 'rm -f "${script_interfaces}" "${script_flows}" \
> +        "${script_datapaths}"' 0 1 2 13 15
> +
> +    action "Saving flows" save_flows
> +
>      # Restart the database first, since a large database may take a
>      # while to load, and we want to minimize forwarding disruption.
>      stop_ovsdb
> @@ -308,8 +349,6 @@ force_reload_kmod () {
>
>      stop_forwarding
>
> -    script=`mktemp`
> -    trap 'rm -f "$script"' 0 1 2 13 15
>      if action "Saving interface configuration" save_interfaces; then
>          :
>      else
> @@ -317,9 +356,18 @@ force_reload_kmod () {
>          start_forwarding
>          exit 1
>      fi
> -    chmod +x "$script"
> +    chmod +x "$script_interfaces"
> +
> +    datapaths=`ovs-dpctl dump-dps`
> +    if action "Saving datapath configuration" save_datapaths; then
> +        chmod +x "${script_datapaths}"
> +    else
> +        log_warning_msg "Failed to save datapath configuration. The port\
> +                         numbers may change after the restart"
> +        script_datapaths=""
> +    fi
>
> -    for dp in `ovs-dpctl dump-dps`; do
> +    for dp in ${datapaths}; do
>          action "Removing datapath: $dp" ovs-dpctl del-dp "$dp"
>      done
>
> @@ -337,7 +385,9 @@ force_reload_kmod () {
>
>      start_forwarding
>
> -    action "Restoring interface configuration" "$script"
> +    restore_flows
> +
> +    action "Restoring interface configuration" "$script_interfaces"
>      rc=$?
>      if test $rc = 0; then
>          level=debug
> @@ -346,11 +396,32 @@ force_reload_kmod () {
>      fi
>      log="logger -p daemon.$level -t ovs-save"
>      $log "force-reload-kmod interface restore script exited with status
> $rc:"
> -    $log -f "$script"
> +    $log -f "$script_interfaces"
>
>      "$datadir/scripts/ovs-check-dead-ifs"
>  }
>
> +## ------- ##
> +## restart ##
> +## ------- ##
> +
> +restart () {
> +    script_flows=`mktemp`
> +    trap 'rm -f "${script_flows}"' 0 1 2 13 15
> +
> +    action "Saving flows" save_flows
> +
> +    # Restart the database first, since a large database may take a
> +    # while to load, and we want to minimize forwarding disruption.
> +    stop_ovsdb
> +    start_ovsdb
> +
> +    stop_forwarding
> +    start_forwarding
> +
> +    restore_flows
> +}
> +
>  ## --------------- ##
>  ## enable-protocol ##
>  ## --------------- ##
> @@ -455,6 +526,7 @@ scripts.  System administrators should not normally
> invoke it directly.
>  Commands:
>    start              start Open vSwitch daemons
>    stop               stop Open vSwitch daemons
> +  restart            stop and start Open vSwitch daemons
>    status             check whether Open vSwitch daemons are running
>    version            print versions of Open vSwitch daemons
>    load-kmod          insert modules if not already present
> @@ -463,18 +535,18 @@ Commands:
>    enable-protocol    enable protocol specified in options with iptables
>    help               display this help message
>
> -One of the following options is required for "start" and
> "force-reload-kmod":
> +One of the following options is required for "start", "restart" and
> "force-reload-kmod":
>    --system-id=UUID   set specific ID to uniquely identify this system
>    --system-id=random  use a random but persistent UUID to identify this
> system
>
> -Other important options for "start" and "force-reload-kmod":
> +Other important options for "start", "restart" and "force-reload-kmod":
>    --system-type=TYPE  set system type (e.g. "XenServer")
>    --system-version=VERSION  set system version (e.g. "5.6.100-39265p")
>    --external-id="key=value"
>                       add given key-value pair to Open_vSwitch external-ids
>    --delete-bridges   delete all bridges just before starting ovs-vswitchd
>
> -Less important options for "start" and "force-reload-kmod":
> +Less important options for "start", "restart" and "force-reload-kmod":
>    --daemon-cwd=DIR               set working dir for OVS daemons
> (default: $DAEMON_CWD)
>    --no-force-corefiles           do not force on core dumps for OVS
> daemons
>    --no-mlockall                  do not lock all of ovs-vswitchd into
> memory
> @@ -482,13 +554,13 @@ Less important options for "start" and
> "force-reload-kmod":
>    --ovs-vswitchd-priority=NICE   set ovs-vswitchd's niceness (default:
> $OVS_VSWITCHD_PRIORITY)
>    --ovs-brcompatd-priority=NICE  set ovs-brcompatd's niceness (default:
> $OVS_BRCOMPATD_PRIORITY)
>
> -Debugging options for "start" and "force-reload-kmod":
> +Debugging options for "start", "restart" and "force-reload-kmod":
>    --ovsdb-server-wrapper=WRAPPER
>    --ovs-vswitchd-wrapper=WRAPPER
>    --ovs-vswitchd-wrapper=WRAPPER
>       run specified daemon under WRAPPER (either 'valgrind' or 'strace')
>
> -Options for "start", "force-reload-kmod", "load-kmod", "status", and
> "version":
> +Options for "start", "restart", "force-reload-kmod", "load-kmod",
> "status", and "version":
>    --brcompat         enable Linux bridge compatibility module and daemon
>
>  File location options:
> @@ -606,6 +678,9 @@ case $command in
>          stop_forwarding
>          stop_ovsdb
>          ;;
> +    restart)
> +        restart
> +        ;;
>      status)
>          rc=0
>          for daemon in `daemons`; do
> @@ -639,4 +714,3 @@ case $command in
>          exit 1
>          ;;
>  esac
> -
> diff --git a/utilities/ovs-save b/utilities/ovs-save
> index 297c2fa..ca29ae8 100755
> --- a/utilities/ovs-save
> +++ b/utilities/ovs-save
> @@ -14,20 +14,25 @@
>  # See the License for the specific language governing permissions and
>  # limitations under the License.
>
> -if test "X$1" = X--help; then
> +usage() {
> +    UTIL=$(basename $0)
>      cat <<EOF
> -$0: saves the kernel configuration of network interfaces
> -usage: $0 NETDEV...
> +${UTIL}: Provides helper functions to save Open vSwitch's configuration.
> +usage: $0 COMMAND
>
> -Outputs a shell script on stdout that will restore the current
> -kernel configuration of the specified network interfaces, as
> -well as the system iptables configuration.
> +Commands:
> + save-interfaces        Outputs a shell script on stdout that will restore
> +                        the current kernel configuration of the specified
> +                        network interfaces, as well as the system iptables
> +                        configuration.
> + save-flows             Outputs a shell script on stdout that will restore
> +                        Openflow flows of each Open vSwitch bridge.
> + save-datapaths         Outputs a shell script on stdout that will restore
> +                        the datapaths with the same port numbers as
> before.
>
> -This script is meant as a helper for the Open vSwitch init
> -script "force-reload-kmod" command.
> +This script is meant as a helper for the Open vSwitch init script
> commands.
>  EOF
> -    exit 0
> -fi
> +}
>
>  PATH=/sbin:/bin:/usr/sbin:/usr/bin
>
> @@ -43,116 +48,233 @@ missing_program () {
>      IFS=$save_IFS
>      return 0
>  }
> -if missing_program ip; then
> -    echo "$0: ip not found in $PATH" >&2
> -    exit 1
> -fi
> -
> -if test "$#" = 0; then
> -    echo "# $0: no parameters given (use \"$0 --help\" for help)"
> -fi
> -
> -devs=$*
> -for dev in $devs; do
> -    state=`ip link show dev $dev` || continue
> -
> -    echo "# $dev"
> -    # Link state (Ethernet addresses, up/down, ...)
> -    linkcmd=
> -    case $state in
> -        *"state UP"* | *[,\<]"UP"[,\>]* )
> -            linkcmd="$linkcmd up"
> -            ;;
> -        *"state DOWN"*)
> -            linkcmd="$linkcmd down"
> -            ;;
> -    esac
> -    if expr "$state" : '.*\bdynamic\b' > /dev/null; then
> -        linkcmd="$linkcmd dynamic"
> -    fi
> -    if qlen=`expr "$state" : '.*qlen \([0-9]+\)'`; then
> -        linkcmd="$linkcmd txqueuelen $qlen"
> -    fi
> -    if hwaddr=`expr "$state" : '.*link/ether \([^ ]*\)'`; then
> -        linkcmd="$linkcmd address $hwaddr"
> -    fi
> -    if brd=`expr "$state" : '.*brd \([^ ]*\)'`; then
> -        linkcmd="$linkcmd broadcast $brd"
> -    fi
> -    if mtu=`expr "$state" : '.*mtu \([0-9]+\)'`; then
> -        linkcmd="$linkcmd mtu $mtu"
> +
> +save_interfaces () {
> +    if missing_program ip; then
> +        echo "$0: ip not found in $PATH" >&2
> +        exit 1
>      fi
> -    if test -n "$linkcmd"; then
> -        echo ip link set dev $dev down # Required to change hwaddr.
> -        echo ip link set dev $dev $linkcmd
> +
> +    if test "$#" = 0; then
> +        exit 0
>      fi
>
> -    # IP addresses (including IPv6).
> -    echo "ip addr flush dev $dev 2>/dev/null" # Suppresses "Nothing to
> flush".
> -    ip addr show dev $dev | while read addr; do
> -        set -- $addr
> -
> -        # Check and trim family.
> -        family=$1
> -        shift
> -        case $family in
> -            inet | inet6) ;;
> -            *) continue ;;
> +    devs="$@"
> +    for dev in $devs; do
> +        state=`ip link show dev $dev` || continue
> +
> +        echo "# $dev"
> +        # Link state (Ethernet addresses, up/down, ...)
> +        linkcmd=
> +        case $state in
> +            *"state UP"* | *[,\<]"UP"[,\>]* )
> +                linkcmd="$linkcmd up"
> +                ;;
> +            *"state DOWN"*)
> +                linkcmd="$linkcmd down"
> +                ;;
>          esac
> +        if expr "$state" : '.*\bdynamic\b' > /dev/null; then
> +            linkcmd="$linkcmd dynamic"
> +        fi
> +        if qlen=`expr "$state" : '.*qlen \([0-9]+\)'`; then
> +            linkcmd="$linkcmd txqueuelen $qlen"
> +        fi
> +        if hwaddr=`expr "$state" : '.*link/ether \([^ ]*\)'`; then
> +            linkcmd="$linkcmd address $hwaddr"
> +        fi
> +        if brd=`expr "$state" : '.*brd \([^ ]*\)'`; then
> +            linkcmd="$linkcmd broadcast $brd"
> +        fi
> +        if mtu=`expr "$state" : '.*mtu \([0-9]+\)'`; then
> +            linkcmd="$linkcmd mtu $mtu"
> +        fi
> +        if test -n "$linkcmd"; then
> +            echo ip link set dev $dev down # Required to change hwaddr.
> +            echo ip link set dev $dev $linkcmd
> +        fi
> +
> +        # IP addresses (including IPv6).
> +        echo "ip addr flush dev $dev 2>/dev/null" # Suppresses "Nothing
> to flush".
> +        ip addr show dev $dev | while read addr; do
> +            set -- $addr
> +
> +            # Check and trim family.
> +            family=$1
> +            shift
> +            case $family in
> +                inet | inet6) ;;
> +                *) continue ;;
> +            esac
>
> -        # Trim device off the end--"ip" insists on having "dev" precede
> it.
> -        addrcmd=
> -        while test $# != 0; do
> -            case $1 in
> -                dynamic)
> -                    # Omit kernel-maintained route.
> -                    continue 2
> -                    ;;
> -                scope)
> -                    if test "$2" = link; then
> -                        # Omit route derived from IP address, e.g.
> -                        # 172.16.0.0/16 derived from 172.16.12.34.
> +            # Trim device off the end--"ip" insists on having "dev"
> precede it.
> +            addrcmd=
> +            while test $# != 0; do
> +                case $1 in
> +                    dynamic)
> +                        # Omit kernel-maintained route.
>                          continue 2
> -                    fi
> -                    ;;
> -                "$dev"|"$dev:"*)
> -                    # Address label string
> -                    addrcmd="$addrcmd label $1"
> -                    shift
> -                    continue
> -                    ;;
> +                        ;;
> +                    scope)
> +                        if test "$2" = link; then
> +                            # Omit route derived from IP address, e.g.
> +                            # 172.16.0.0/16 derived from 172.16.12.34.
> +                            continue 2
> +                        fi
> +                        ;;
> +                    "$dev"|"$dev:"*)
> +                        # Address label string
> +                        addrcmd="$addrcmd label $1"
> +                        shift
> +                        continue
> +                        ;;
> +                esac
> +                addrcmd="$addrcmd $1"
> +                shift
> +            done
> +            if test "$1" != "$dev"; then
> +                addrcmd="$addrcmd $1"
> +            fi
> +
> +            echo ip -f $family addr add $addrcmd dev $dev
> +        done
> +
> +        # Routes.
> +        echo "ip route flush dev $dev proto boot 2>/dev/null" #
> Suppresses "Nothing to flush".
> +        ip route show dev $dev | while read route; do
> +            # "proto kernel" routes are installed by the kernel
> automatically.
> +            case $route in
> +                *" proto kernel "*) continue ;;
>              esac
> -            addrcmd="$addrcmd $1"
> -            shift
> +
> +            echo "ip route add $route dev $dev"
>          done
> -        if test "$1" != "$dev"; then
> -            addrcmd="$addrcmd $1"
> -        fi
>
> -        echo ip -f $family addr add $addrcmd dev $dev
> +        echo
>      done
>
> -    # Routes.
> -    echo "ip route flush dev $dev proto boot 2>/dev/null" # Suppresses
> "Nothing to flush".
> -    ip route show dev $dev | while read route; do
> -        # "proto kernel" routes are installed by the kernel automatically.
> -        case $route in
> -            *" proto kernel "*) continue ;;
> -        esac
> +    if missing_program iptables-save; then
> +        echo "# iptables-save not found in $PATH, not saving iptables
> state"
> +    else
> +        echo "# global"
> +        echo "iptables-restore <<'EOF'"
> +        iptables-save
> +        echo "EOF"
> +    fi
> +}
> +
> +save_flows () {
> +    if missing_program ovs-ofctl; then
> +        echo "$0: ovs-ofctl not found in $PATH" >&2
> +        exit 1
> +    fi
>
> -        echo "ip route add $route dev $dev"
> +    for bridge in "$@"; do
> +        echo "ovs-ofctl add-flows ${bridge} - << EOF"
> +        ovs-ofctl dump-flows "${bridge}" | sed -e '/NXST_FLOW/d' \
> +            -e 's/\(idle\|hard\)_age=[^,]*,//g'
> +        echo "EOF"
>      done
> +}
>
> -    echo
> -done
> +save_datapaths () {
> +    if missing_program ovs-dpctl; then
> +        echo "$0: ovs-dpctl not found in $PATH" >&2
> +        exit 1
> +    fi
> +    if missing_program ovs-vsctl; then
> +        echo "$0: ovs-vsctl not found in $PATH" >&2
> +        exit 1
> +    fi
> +
> +    for dp in "$@"; do
> +        echo "ovs-dpctl add-dp ${dp}"
> +        ovs-dpctl show $dp | while read line; do
> +            # An example 'ovs-dpctl show' output looks like this:
> +            # system at br1:
> +            # lookups: hit:0 missed:0 lost:0
> +            # flows: 0
> +            # port 0: br1 (internal)
> +            # port 2: gre2886795521 (ipsec_gre: key=flow, pmtud=false,
> remote_ip=172.17.1.1, tos=inherit)
> +            # port 3: gre1 (ipsec_gre: remote_ip=192.168.113.1)
> +            # port 14: gre2 (gre: remote_ip=192.168.115.1)
> +            # port 15: gre3 (gre64: remote_ip=192.168.116.1)
> +            # port 16: eth0
> +            # port 17: br1- (patch: peer=br1+)
>
> -if missing_program iptables-save; then
> -    echo "# iptables-save not found in $PATH, not saving iptables state"
> -else
> -    echo "# global"
> -    echo "iptables-restore <<'EOF'"
> -    iptables-save
> -    echo "EOF"
> -fi
> +            # Skip lines which do not have 'port'
> +            if port_no=`expr "${line}" : '.*port \([0-9]\+\):'`; then :;
> else
> +                continue
> +            fi
> +
> +            netdev=`echo ${line} | awk '{print $3}'`
> +
> +            # Do not add port that has the same name as the datapath. It
> gets
> +            # added by default.
> +            [ "${dp#system@}" = "${netdev}" ] && continue
> +
> +            type=`echo ${line} | awk '{print $4}' | sed 's/[:)(]//g'`
> +            [ ! -n "${type}" ] && type="system"
> +
> +            command="ovs-dpctl add-if ${dp}\
> +                        ${netdev},type=${type},port_no=${port_no}"
> +
> +            options=`echo ${line} | awk -F: '{print $3}' | sed 's/[)
> ]//g'`
> +            [ -n "${options}" ] && command="${command},${options}"
> +
> +            # For ipsec, ovs-dpctl does not show the key value pairs
> related
> +            # to certificates. Get that information from ovs-vsctl.
> +            if [ "${type}" = "ipsec_gre" ] ; then
> +                if peer_cert=`ovs-vsctl get interface \
> +                                "${netdev}" options:peer_cert
> 2>/dev/null`; then
> +                    # The option peer_cert comes with an accompanying
> +                    # "certificate" or "use_ssl_cert"
> +                    if (ovs-vsctl get interface "${netdev}" \
> +                            options:certificate >/dev/null 2>&1) ; then
>
Thank you for the review. I will change the above line to
+                    if certificate=`ovs-vsctl get interface "${netdev}" \
                            options:certificate 2>/dev/null` ; then
and push this.


> +
>  command="${command},peer_cert=${peer_cert},certificate=${certificate}"
> +                    else
> +                        use_ssl_cert=`ovs-vsctl get interface "${netdev}"
> \
> +                                        options:use_ssl_cert 2>/dev/null`
> +
>  command="${command},peer_cert=${peer_cert},use_ssl_cert=${use_ssl_cert}"
> +                    fi
> +                else
> +                    psk=`ovs-vsctl get interface "${netdev}" \
> +                            options:psk 2>/dev/null`
> +                    command="${command},psk=${psk}"
> +                fi
> +            fi
> +            echo ${command}
> +        done
> +    done
> +}
> +
> +while [ $# -ne 0 ]
> +do
> +    case $1 in
> +        "save-datapaths")
> +            shift
> +            save_datapaths "$@"
> +            exit 0
> +            ;;
> +        "save-flows")
> +            shift
> +            save_flows "$@"
> +            exit 0
> +            ;;
> +        "save-interfaces")
> +            shift
> +            save_interfaces "$@"
> +            exit 0
> +            ;;
> +        -h | --help)
> +            usage
> +            exit 0
> +            ;;
> +        *)
> +            echo >&2 "$0: unknown command \"$1\" (use --help for help)"
> +            exit 1
> +            ;;
> +    esac
> +done
>
>  exit 0
> --
> 1.7.2.5
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openvswitch.org/pipermail/ovs-dev/attachments/20121023/af175dce/attachment-0003.html>


More information about the dev mailing list