You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
5.8 KiB

  1. #!/bin/sh /etc/rc.common
  2. # Copyright (C) 2013 Julius Schulz-Zander <julius@net.t-labs.tu-berlin.de>
  3. # Copyright (C) 2014-2017 OpenWrt.org
  4. # Copyright (C) 2018 Yousong Zhou <yszhou4tech@gmail.com>
  5. # Copyright (C) 2021 Felix Fietkau <nbd@nbd.name>
  6. . /lib/functions/procd.sh
  7. START=15
  8. basescript=$(readlink "$initscript")
  9. ovs_ctl="/usr/share/openvswitch/scripts/ovs-ctl"; [ -x "$ovs_ctl" ] || ovs_ctl=:
  10. ovn_ctl="/usr/share/ovn/scripts/ovn-ctl"; [ -x "$ovn_ctl" ] || ovn_ctl=:
  11. extra_command "status" "Get status information"
  12. service_triggers() {
  13. procd_add_reload_trigger openvswitch
  14. }
  15. init_triggers() {
  16. procd_open_service "$(basename ${basescript:-$initscript})" "$initscript"
  17. procd_close_service set
  18. }
  19. start() {
  20. init_triggers
  21. ovs_action start "$@"
  22. }
  23. reload() {
  24. start
  25. }
  26. running() {
  27. return 0
  28. }
  29. stop() {
  30. procd_kill "$(basename ${basescript:-$initscript})"
  31. ovs_action stop "$@"
  32. }
  33. restart() {
  34. init_triggers
  35. ovs_action restart "$@"
  36. }
  37. status() {
  38. ovs_action status "$@"
  39. }
  40. ovs_action_cfgs=
  41. ovs_action() {
  42. local action="$1"; shift
  43. local cfgtype
  44. ovs_action_cfgs="$*"
  45. config_load openvswitch
  46. for cfgtype in ovs ovn_northd ovn_controller; do
  47. config_foreach "ovs_xx" "$cfgtype" "$action" "$cfgtype"
  48. done
  49. case "$action" in
  50. restart|start)
  51. config_foreach ovs_bridge_init "ovs_bridge"
  52. ;;
  53. esac
  54. }
  55. ovs_xx() {
  56. local cfg="$1"
  57. local action="$2"
  58. local cfgtype="$3"
  59. local disabled
  60. if [ -n "$ovs_action_cfgs" ] && ! list_contains "ovs_action_cfgs" "$cfg"; then
  61. return
  62. fi
  63. case "$action" in
  64. status|stop) ;;
  65. *)
  66. config_get_bool disabled "$cfg" disabled 0
  67. [ "$disabled" == "0" ] || return
  68. ;;
  69. esac
  70. case "$cfgtype" in
  71. ovs)
  72. "$ovs_ctl" "$action" \
  73. --system-id=random 1000>&-
  74. ovs_set_ssl
  75. ;;
  76. ovn_*)
  77. "$ovn_ctl" "${action}_${cfgtype#ovn_}"
  78. ;;
  79. esac
  80. }
  81. ovs_bridge_parse_port() {
  82. case "$1" in
  83. *:*)
  84. port="${1%%:*}"
  85. type="${1#*:}"
  86. ;;
  87. *)
  88. port="$1"
  89. type=""
  90. ;;
  91. esac
  92. }
  93. ovs_bridge_port_add() {
  94. [ -n "$1" ] || return
  95. ovs_bridge_parse_port "$1"
  96. cur_type="$(ovs-vsctl get interface "$port" type 2>/dev/null)"
  97. [ "$?" = 0 ] && {
  98. [ "$type" = "$cur_type" ] || ovs-vsctl del-port "$port"
  99. }
  100. ovs-vsctl --may-exist add-port "$name" "$port" ${type:+ -- set interface "$port" type="$type"}
  101. ovs_bridge_port_up "$port"
  102. __port_list="$__port_list ${port} "
  103. }
  104. ovs_bridge_port_add_complex() {
  105. local cfg="$1"
  106. local cur_bridge="$2"
  107. local bridge disabled ofport port tag type
  108. local cur_tag cur_type del_port
  109. config_get_bool disabled "$cfg" disabled 0
  110. [ "$disabled" = "0" ] || return
  111. config_get bridge "$cfg" bridge
  112. [ "$bridge" = "$cur_bridge" ] || return
  113. ovs-vsctl br-exists "$bridge" || return
  114. config_get port "$cfg" port
  115. [ -n "$port" ] || return
  116. config_get ofport "$cfg" ofport
  117. config_get tag "$cfg" tag
  118. if [ -n "$tag" ]; then
  119. if cur_tag="$(ovs-vsctl get port "$port" tag 2>/dev/null)"; then
  120. [ "$tag" = "$cur_tag" ] || del_port=1
  121. fi
  122. fi
  123. config_get type "$cfg" type
  124. if [ -n "$type" ]; then
  125. if cur_type="$(ovs-vsctl get interface "$port" type 2>/dev/null)"; then
  126. [ "$type" = "$cur_type" ] || del_port=1
  127. fi
  128. fi
  129. [ "${del_port:-0}" -eq 1 ] && ovs-vsctl --if-exists del-port "$bridge" "$port"
  130. ovs-vsctl --may-exist add-port "$bridge" "$port" ${tag:+tag="$tag"} \
  131. ${ofport:+ -- set interface "$port" ofport_request="$ofport"} \
  132. ${type:+ -- set interface "$port" type="$type"}
  133. ovs_bridge_port_up "$port"
  134. __port_list="$__port_list ${port} "
  135. }
  136. ovs_bridge_port_cleanup() {
  137. for port in `ovs-vsctl list-ports "$name"`; do
  138. case "$__port_list" in
  139. *" $port "*);;
  140. *) ovs-vsctl del-port "$port";;
  141. esac
  142. done
  143. }
  144. ovs_bridge_port_up() {
  145. local port="$1"
  146. ip link set dev "$port" up
  147. }
  148. ovs_bridge_validate_datapath_id() {
  149. local dpid="$1"
  150. if expr "$dpid" : '[[:xdigit:]]\{16\}$' > /dev/null; then
  151. return 0
  152. elif expr "$dpid" : '0x[[:xdigit:]]\{1,16\}$' > /dev/null; then
  153. return 0
  154. else
  155. logger -t openvswitch "invalid datapath_id: $dpid"
  156. return 1
  157. fi
  158. }
  159. ovs_bridge_validate_datapath_desc() {
  160. local dpdesc="$1"
  161. if [ "$(echo $dpdesc | wc -c)" -le 255 ]; then
  162. return 0
  163. else
  164. logger -t openvswitch "invalid datapath_desc: $dpdesc"
  165. return 1
  166. fi
  167. }
  168. ovs_bridge_validate_fail_mode() {
  169. local fail_mode="$1"
  170. case "$fail_mode" in
  171. secure|standalone)
  172. return 0
  173. ;;
  174. *)
  175. logger -t openvswitch "invalid fail_mode: $fail_mode"
  176. return 1
  177. ;;
  178. esac
  179. }
  180. ovs_bridge_init() {
  181. local cfg="$1"
  182. local disabled
  183. local name
  184. local controller
  185. local datapath_id
  186. config_get_bool disabled "$cfg" disabled 0
  187. [ "$disabled" == "0" ] || return
  188. config_get name "$cfg" name $cfg
  189. ovs-vsctl --may-exist add-br "$name"
  190. config_get datapath_id "$cfg" datapath_id
  191. [ -n "$datapath_id" ] && {
  192. ovs_bridge_validate_datapath_id "$datapath_id" && {
  193. ovs-vsctl --if-exists set bridge "$name" other-config:datapath-id="$datapath_id"
  194. }
  195. }
  196. config_get datapath_desc "$cfg" datapath_desc
  197. [ -n "$datapath_desc" ] && {
  198. ovs_bridge_validate_datapath_desc "$datapath_desc" && {
  199. ovs-vsctl --if-exists set bridge "$name" other-config:dp-desc="$datapath_desc"
  200. }
  201. }
  202. config_get fail_mode "$cfg" fail_mode
  203. [ -n "$fail_mode" ] && {
  204. ovs_bridge_validate_fail_mode "$fail_mode" && {
  205. ovs-vsctl set-fail-mode "$name" "$fail_mode" 2> /dev/null
  206. } || {
  207. ovs-vsctl del-fail-mode "$name" 2> /dev/null
  208. }
  209. } || {
  210. ovs-vsctl del-fail-mode "$name" 2> /dev/null
  211. }
  212. config_list_foreach "$cfg" "ports" ovs_bridge_port_add
  213. config_foreach ovs_bridge_port_add_complex ovs_port "$name"
  214. config_get_bool drop "$cfg" "drop_unknown_ports" 0
  215. [ "$drop" == 1 ] && ovs_bridge_port_cleanup
  216. config_get controller "$cfg" controller
  217. [ -n "$controller" ] && \
  218. ovs-vsctl set-controller "$name" "$controller"
  219. }
  220. ovs_set_ssl() {
  221. local ca="$(uci -q get openvswitch.ovs.ca)"
  222. [ -f "$ca" ] || return
  223. local cert="$(uci get openvswitch.ovs.cert)"
  224. [ -f "$cert" ] || return
  225. local key="$(uci get openvswitch.ovs.key)"
  226. [ -f "$key" ] || return
  227. ovs-vsctl set-ssl "$key" "$cert" "$ca"
  228. }