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