| #!/bin/sh /etc/rc.common |
| # Copyright (C) 2013 Julius Schulz-Zander <julius@net.t-labs.tu-berlin.de> |
| # Copyright (C) 2014-2017 OpenWrt.org |
| # Copyright (C) 2018 Yousong Zhou <yszhou4tech@gmail.com> |
| # Copyright (C) 2021 Felix Fietkau <nbd@nbd.name> |
| |
| . /lib/functions/procd.sh |
| START=15 |
| |
| basescript=$(readlink "$initscript") |
| |
| ovs_ctl="/usr/share/openvswitch/scripts/ovs-ctl"; [ -x "$ovs_ctl" ] || ovs_ctl=: |
| ovn_ctl="/usr/share/ovn/scripts/ovn-ctl"; [ -x "$ovn_ctl" ] || ovn_ctl=: |
| |
| extra_command "status" "Get status information" |
| |
| service_triggers() { |
| procd_add_reload_trigger openvswitch |
| } |
| |
| init_triggers() { |
| procd_open_service "$(basename ${basescript:-$initscript})" "$initscript" |
| procd_close_service set |
| } |
| |
| start() { |
| init_triggers |
| ovs_action start "$@" |
| } |
| |
| reload() { |
| start |
| } |
| |
| running() { |
| return 0 |
| } |
| |
| stop() { |
| procd_kill "$(basename ${basescript:-$initscript})" |
| ovs_action stop "$@" |
| } |
| |
| restart() { |
| init_triggers |
| ovs_action restart "$@" |
| } |
| |
| status() { |
| ovs_action status "$@" |
| } |
| |
| ovs_action_cfgs= |
| ovs_action() { |
| local action="$1"; shift |
| local cfgtype |
| |
| ovs_action_cfgs="$*" |
| config_load openvswitch |
| for cfgtype in ovs ovn_northd ovn_controller; do |
| config_foreach "ovs_xx" "$cfgtype" "$action" "$cfgtype" |
| done |
| |
| case "$action" in |
| restart|start) |
| config_foreach ovs_bridge_init "ovs_bridge" |
| ;; |
| esac |
| |
| } |
| |
| ovs_xx() { |
| local cfg="$1" |
| local action="$2" |
| local cfgtype="$3" |
| local disabled |
| |
| if [ -n "$ovs_action_cfgs" ] && ! list_contains "ovs_action_cfgs" "$cfg"; then |
| return |
| fi |
| case "$action" in |
| status|stop) ;; |
| *) |
| config_get_bool disabled "$cfg" disabled 0 |
| [ "$disabled" == "0" ] || return |
| ;; |
| esac |
| |
| case "$cfgtype" in |
| ovs) |
| "$ovs_ctl" "$action" \ |
| --system-id=random 1000>&- |
| ovs_set_ssl |
| ;; |
| ovn_*) |
| "$ovn_ctl" "${action}_${cfgtype#ovn_}" |
| ;; |
| esac |
| } |
| |
| ovs_bridge_parse_port() { |
| case "$1" in |
| *:*) |
| port="${1%%:*}" |
| type="${1#*:}" |
| ;; |
| *) |
| port="$1" |
| type="" |
| ;; |
| esac |
| } |
| |
| ovs_bridge_port_add() { |
| [ -n "$1" ] || return |
| |
| ovs_bridge_parse_port "$1" |
| cur_type="$(ovs-vsctl get interface "$port" type 2>/dev/null)" |
| [ "$?" = 0 ] && { |
| [ "$type" = "$cur_type" ] || ovs-vsctl del-port "$port" |
| } |
| |
| ovs-vsctl --may-exist add-port "$name" "$port" ${type:+ -- set interface "$port" type="$type"} |
| ovs_bridge_port_up "$port" |
| __port_list="$__port_list ${port} " |
| } |
| |
| ovs_bridge_port_add_complex() { |
| local cfg="$1" |
| local cur_bridge="$2" |
| |
| local bridge disabled ofport port tag type |
| local cur_tag cur_type del_port |
| |
| config_get_bool disabled "$cfg" disabled 0 |
| [ "$disabled" = "0" ] || return |
| |
| config_get bridge "$cfg" bridge |
| [ "$bridge" = "$cur_bridge" ] || return |
| ovs-vsctl br-exists "$bridge" || return |
| |
| config_get port "$cfg" port |
| [ -n "$port" ] || return |
| |
| config_get ofport "$cfg" ofport |
| |
| config_get tag "$cfg" tag |
| if [ -n "$tag" ]; then |
| if cur_tag="$(ovs-vsctl get port "$port" tag 2>/dev/null)"; then |
| [ "$tag" = "$cur_tag" ] || del_port=1 |
| fi |
| fi |
| |
| config_get type "$cfg" type |
| if [ -n "$type" ]; then |
| if cur_type="$(ovs-vsctl get interface "$port" type 2>/dev/null)"; then |
| [ "$type" = "$cur_type" ] || del_port=1 |
| fi |
| fi |
| |
| [ "${del_port:-0}" -eq 1 ] && ovs-vsctl --if-exists del-port "$bridge" "$port" |
| |
| ovs-vsctl --may-exist add-port "$bridge" "$port" ${tag:+tag="$tag"} \ |
| ${ofport:+ -- set interface "$port" ofport_request="$ofport"} \ |
| ${type:+ -- set interface "$port" type="$type"} |
| ovs_bridge_port_up "$port" |
| __port_list="$__port_list ${port} " |
| } |
| |
| ovs_bridge_port_cleanup() { |
| for port in `ovs-vsctl list-ports "$name"`; do |
| case "$__port_list" in |
| *" $port "*);; |
| *) ovs-vsctl del-port "$port";; |
| esac |
| done |
| } |
| |
| ovs_bridge_port_up() { |
| local port="$1" |
| |
| ip link set dev "$port" up |
| } |
| |
| ovs_bridge_validate_datapath_id() { |
| local dpid="$1" |
| |
| if expr "$dpid" : '[[:xdigit:]]\{16\}$' > /dev/null; then |
| return 0 |
| elif expr "$dpid" : '0x[[:xdigit:]]\{1,16\}$' > /dev/null; then |
| return 0 |
| else |
| logger -t openvswitch "invalid datapath_id: $dpid" |
| return 1 |
| fi |
| } |
| |
| ovs_bridge_validate_datapath_desc() { |
| local dpdesc="$1" |
| |
| if [ "$(echo $dpdesc | wc -c)" -le 255 ]; then |
| return 0 |
| else |
| logger -t openvswitch "invalid datapath_desc: $dpdesc" |
| return 1 |
| fi |
| } |
| |
| ovs_bridge_validate_fail_mode() { |
| local fail_mode="$1" |
| |
| case "$fail_mode" in |
| secure|standalone) |
| return 0 |
| ;; |
| *) |
| logger -t openvswitch "invalid fail_mode: $fail_mode" |
| return 1 |
| ;; |
| esac |
| } |
| |
| ovs_bridge_init() { |
| local cfg="$1" |
| |
| local disabled |
| local name |
| local controller |
| local datapath_id |
| |
| config_get_bool disabled "$cfg" disabled 0 |
| [ "$disabled" == "0" ] || return |
| |
| config_get name "$cfg" name $cfg |
| ovs-vsctl --may-exist add-br "$name" |
| |
| config_get datapath_id "$cfg" datapath_id |
| [ -n "$datapath_id" ] && { |
| ovs_bridge_validate_datapath_id "$datapath_id" && { |
| ovs-vsctl --if-exists set bridge "$name" other-config:datapath-id="$datapath_id" |
| } |
| } |
| |
| config_get datapath_desc "$cfg" datapath_desc |
| [ -n "$datapath_desc" ] && { |
| ovs_bridge_validate_datapath_desc "$datapath_desc" && { |
| ovs-vsctl --if-exists set bridge "$name" other-config:dp-desc="$datapath_desc" |
| } |
| } |
| |
| config_get fail_mode "$cfg" fail_mode |
| [ -n "$fail_mode" ] && { |
| ovs_bridge_validate_fail_mode "$fail_mode" && { |
| ovs-vsctl set-fail-mode "$name" "$fail_mode" 2> /dev/null |
| } || { |
| ovs-vsctl del-fail-mode "$name" 2> /dev/null |
| } |
| } || { |
| ovs-vsctl del-fail-mode "$name" 2> /dev/null |
| } |
| |
| config_list_foreach "$cfg" "ports" ovs_bridge_port_add |
| config_foreach ovs_bridge_port_add_complex ovs_port "$name" |
| config_get_bool drop "$cfg" "drop_unknown_ports" 0 |
| [ "$drop" == 1 ] && ovs_bridge_port_cleanup |
| |
| config_get controller "$cfg" controller |
| [ -n "$controller" ] && \ |
| ovs-vsctl set-controller "$name" "$controller" |
| } |
| |
| ovs_set_ssl() { |
| local ca="$(uci -q get openvswitch.ovs.ca)" |
| [ -f "$ca" ] || return |
| local cert="$(uci get openvswitch.ovs.cert)" |
| [ -f "$cert" ] || return |
| local key="$(uci get openvswitch.ovs.key)" |
| [ -f "$key" ] || return |
| |
| ovs-vsctl set-ssl "$key" "$cert" "$ca" |
| } |