ipw 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. #!/bin/bash
  2. # Copyright (C) 2013 Artyom A Anikeev <anikeev@ut.mephi.ru> 0xB5385841,
  3. # Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. CMD="$1"; shift;
  18. DEFAULT_BONDING_MODE='balance-tlb'
  19. LXC_ISV2="$(lxc --version 2>/dev/null)"
  20. modprobe bonding
  21. if lockfile-check /run/ipw; then
  22. eerror 'Another "ipw" instance is already running'
  23. exit -1
  24. fi
  25. trap 'lockfile-remove /run/ipw' SIGINT SIGTERM SIGHUP SIGQUIT SIGALRM SIGILL SIGABRT SIGPIPE EXIT
  26. lockfile-create /run/ipw || exit
  27. eerror() {
  28. echo "$@" >&2
  29. }
  30. newconfig_open() {
  31. echo -n > "$NEWCONFIG_TMPPATH"
  32. }
  33. newconfig_write() {
  34. LINE="$1"; shift;
  35. [[ "$NEWCONFIG" -eq 0 ]] && return
  36. echo "$LINE" >> "$NEWCONFIG_TMPPATH"
  37. }
  38. newconfig_commit() {
  39. rm -f "$CONFIG_PATH"
  40. mv "$NEWCONFIG_TMPPATH" "$CONFIG_PATH"
  41. }
  42. newconfig_push() {
  43. BUFNUM="$1"; shift;
  44. LINE="$1"; shift;
  45. BUF[$BUFNUM]="${BUF[$BUFNUM]}
  46. $LINE"
  47. }
  48. newconfig_pushpopall() {
  49. BUFNUMTO="$1"; shift;
  50. BUFNUMFROM="$1"; shift;
  51. newconfig_push "$BUFNUMTO" "${BUF[$BUFNUMFROM]}"
  52. newconfig_popall "$BUFNUMFROM"
  53. }
  54. newconfig_popall() {
  55. BUFNUM="$1"; shift;
  56. BUF[$BUFNUM]=""
  57. }
  58. newconfig_popallwrite() {
  59. BUFNUM="$1"; shift;
  60. newconfig_write "${BUF[$BUFNUM]}"
  61. BUF[$BUFNUM]=""
  62. }
  63. # INPUT: 10.2:thor.ext; OUTPUT: environments: VLAN, SUBVLAN, BRNAME
  64. parse_vlan_subvlan_bridge() {
  65. VLAN_N_BRIDGE="$1"; shift
  66. if [[ "${VLAN_N_BRIDGE:0:1}" = ":" ]]; then
  67. VLAN=""
  68. SUBVLAN=""
  69. VLANNAME=""
  70. BRNAME="${VLAN_N_BRIDGE:1}"
  71. else
  72. # Splitting by ":"
  73. WORDS=( ${VLAN_N_BRIDGE//[:]/ } )
  74. # The second word defines interface name. If it's empty, "vlan$VLAN.$SUBVLAN" is used.
  75. VLANNAME="${WORDS[0]}"
  76. BRNAME="${WORDS[1]}"
  77. # Splitting by "."
  78. WORDS=( ${VLANNAME//[.]/ } )
  79. # The second word defines subvlan (1q-in-1q) if it's used. It's empty if no subvlan is used.
  80. VLAN="${WORDS[0]}"
  81. SUBVLAN="${WORDS[1]}"
  82. fi
  83. # Checking if no "vlan(.subvlan)?" is set
  84. if ! [[ "${VLAN_N_BRIDGE: -1}" = ":" ]]; then
  85. # Setting default values
  86. [[ "$SUBVLAN" = "" ]] && BRNAME="${BRNAME:-vlan${VLAN}}" || BRNAME="${BRNAME:-vlan${VLAN}.${SUBVLAN}}"
  87. fi
  88. return;
  89. }
  90. declare -A get_brname_byslave_assoc
  91. for VLAN_N_BRIDGE in $(find /sys/devices/virtual/net -wholename '*/brif/*' | awk -F '/' '{print $8":"$6}'); do
  92. oldIFS="$IFS"; IFS=':'; words=($VLAN_N_BRIDGE); IFS="$oldIFS"
  93. get_brname_byslave_assoc[${words[0]}]=${words[1]}
  94. done
  95. get_brname_byslave() {
  96. _SLAVE="$1"; shift
  97. echo ${get_brname_byslave_assoc[$_SLAVE]}
  98. }
  99. get_vlan_n_bridges() {
  100. awk '{if(NR>2) if( system( "[ -d /sys/devices/virtual/net/*/brif/"$1" ] " ) != 0 ) print $1":"}' < /proc/1/net/vlan/config
  101. find /sys/devices/virtual/net -wholename '*/brif' -empty | awk -F '/' '{print ":"$6}'
  102. find /sys/devices/virtual/net -wholename '*/brif/*' | awk -F '/' '{print $8":"$6}'
  103. }
  104. iface_isexists() {
  105. _IFACE="$1"; shift;
  106. [ -e /sys/devices/virtual/net/"$_IFACE" ]
  107. return $?
  108. }
  109. IPW_FAST="${IPW_FAST:-0}"
  110. if [[ "$IPW_FAST" -ne '0' ]]; then
  111. declare -A IFACE_DETAILS
  112. oldIFS="$IFS"; IFS="\n"
  113. for LINE in $(ip -o address show | tr -d ':' | grep -v '<'); do
  114. WORDS=( ${LINE//[:]/ } )
  115. [[ "${WORDS[2]}" = 'inet' ]]
  116. IFACE_DETAILS["${WORDS[1]}-primary-ipv4address"]="${WORDS[3]}"
  117. done
  118. IFS="$oldIFS"
  119. fi
  120. ip_cmds() {
  121. _IFACE="$1"; shift
  122. IP_CMDS_VARIABLE="${_IFACE//[.]/_}_IP"
  123. IP_CMDS_VARIABLE="${IP_CMDS_VARIABLE}[@]"
  124. [[ "$IPW_FAST" -ne 0 ]] &&
  125. # Don't do anything if the interface should be "empty" and it's already is
  126. [[ "${!IP_CMDS_VARIABLE}" = '' ]] &&
  127. [[ "${IFACE_DETAILS[${_IFACE}-primary-ipv4address]}" != '' ]] &&
  128. return
  129. ip addr flush dev "$_IFACE"
  130. for IP_CMD in "${!IP_CMDS_VARIABLE}"; do
  131. if [[ "$IP_CMD" != "" ]]; then
  132. WORDS=($IP_CMD)
  133. case "${WORDS[0]}" in
  134. link)
  135. ip $IP_CMD
  136. ;;
  137. *)
  138. ip $IP_CMD dev "$_IFACE"
  139. esac
  140. fi
  141. done
  142. }
  143. case "$CMD" in
  144. down)
  145. IPW_CONFIG_PATH=/dev/null
  146. CMD='fix'
  147. ;;
  148. esac
  149. IPW_CONFIG_PATH="${IPW_CONFIG_PATH:-/etc/ipw.conf}"
  150. BRIDGE_FORWARD_DELAY=0
  151. source "$IPW_CONFIG_PATH"
  152. if [ "$LXC_ISV2" != "" ]; then
  153. LXC_DIR=""
  154. fi
  155. declare -A SKIP_BRIDGE_MAP
  156. for SKIP_BRIDGE in ${SKIP_BRIDGES[@]}; do
  157. SKIP_BRIDGES_MAP[$SKIP_BRIDGE]=1
  158. done
  159. NEWCONFIG_TMPPATH="/tmp/.~ipw"
  160. NEWCONFIG=0
  161. case "$CMD" in
  162. add1qif) #allow to add slave interface in bonding
  163. NEWCONFIG=1 # we need to update the config after the command
  164. NEW_D1Q_IFACE="$1"; shift
  165. NEW_SLAVE="$1"; shift
  166. # checking for duplicated slaves or d1q_ifaces
  167. D1Q_IFACE_USED=0
  168. for D1Q_IFACE in ${D1Q_IFACES[@]}; do
  169. if [[ "$D1Q_IFACE" = "$NEW_D1Q_IFACE" ]]; then
  170. D1Q_IFACE_USED=1
  171. fi
  172. SLAVES_VARIABLE="${D1Q_IFACE}_SLAVES"
  173. SLAVES_VARIABLE="${SLAVES_VARIABLE//[.]/_}[@]"
  174. for SLAVE in "${!SLAVES_VARIABLE}"; do
  175. if [[ "$SLAVE" = "$NEW_SLAVE" ]]; then
  176. eerror "This interface have already been enslaved"
  177. exit -1
  178. fi
  179. done
  180. done
  181. if [[ $D1Q_IFACE_USED -eq 0 ]]; then
  182. D1Q_IFACES[ ${#D1Q_IFACES} ]="$NEW_D1Q_IFACE"
  183. fi
  184. SLAVES_VARIABLE="${NEW_D1Q_IFACE}_SLAVES"
  185. SLAVES_VARIABLE="${SLAVES_VARIABLE//[.]/_}"
  186. eval "${SLAVES_VARIABLE}[\${#${SLAVES_VARIABLE}}]=\"$NEW_SLAVE\""
  187. ;;
  188. del1qif)
  189. ;;
  190. addbrif) #allow to add bridge/vlan in bonding
  191. NEWCONFIG=1 # we need to update the config after the command
  192. NEW_D1Q_IFACE="$1"; shift
  193. NEW_VLAN_SUBVLAN="$1"; shift
  194. NEW_BRIDGE="$1"; shift
  195. [[ -z $NEW_BRIDGE ]] && NEW_VLAN_N_BRIDGE="${NEW_VLAN_SUBVLAN}" || NEW_VLAN_N_BRIDGE="${NEW_VLAN_SUBVLAN}:${NEW_BRIDGE}"
  196. D1Q_IFACE_USED=0
  197. for D1Q_IFACE in ${D1Q_IFACES[@]}; do
  198. if [[ "$D1Q_IFACE" = "$NEW_D1Q_IFACE" ]]; then
  199. D1Q_IFACE_USED=1
  200. break;
  201. fi
  202. done
  203. parse_vlan_subvlan_bridge "${NEW_VLAN_N_BRIDGE}"
  204. NEW_VLAN=$VLAN
  205. NEW_SUBVLAN=$SUBVLAN
  206. if [[ $D1Q_IFACE_USED -eq 0 ]]; then
  207. eerror "There's no such interface: $NEW_D1Q_IFACE"
  208. exit -1
  209. fi
  210. VLAN_N_BRIDGE_VARIABLE="${NEW_D1Q_IFACE}_VLAN_N_BRIDGES"
  211. VLAN_N_BRIDGE_VARIABLE="${VLAN_N_BRIDGE_VARIABLE//[.]/_}[@]"
  212. for VLAN_N_BRIDGE in "${!VLAN_N_BRIDGE_VARIABLE}"; do
  213. parse_vlan_subvlan_bridge "${VLAN_N_BRIDGE}"
  214. if [[ "$VLAN" = "$NEW_VLAN" && "$SUBVLAN" = "$NEW_SUBVLAN" ]]; then
  215. eerror "This vlan is alredy used"
  216. exit -1
  217. fi
  218. done
  219. VLAN_N_BRIDGE_VARIABLE="${NEW_D1Q_IFACE}_VLAN_N_BRIDGES"
  220. VLAN_N_BRIDGE_VARIABLE="${VLAN_N_BRIDGE_VARIABLE//[.]/_}"
  221. eval "${VLAN_N_BRIDGE_VARIABLE}[\${#${VLAN_N_BRIDGE_VARIABLE}}]=\"$NEW_VLAN_N_BRIDGE\""
  222. #D1Q_IFACES[ ${#D1Q_IFACES}]
  223. ;;
  224. delbrif)
  225. ;;
  226. addbr) #allow to add bridge without interfaces
  227. NEWCONFIG=1 # we need to update the config after the command
  228. NEW_D1Q_IFACE="$1"; shift
  229. NEW_BRIDGE="$1"; shift
  230. VLAN_N_BRIDGE_VARIABLE="${NEW_D1Q_IFACE}_VLAN_N_BRIDGES"
  231. VLAN_N_BRIDGE_VARIABLE="${VLAN_N_BRIDGE_VARIABLE//[.]/_}"
  232. eval "${VLAN_N_BRIDGE_VARIABLE}[\${#${VLAN_N_BRIDGE_VARIABLE}}]=\":${NEW_BRIDGE}\""
  233. ;;
  234. delbr)
  235. ;;
  236. addif) #allow to add interface without bridging
  237. ;;
  238. delif)
  239. ;;
  240. addipcmd) #allow to add ip commnds for bridges/vlans
  241. NEWCONFIG=1 # we need to update the config after the command
  242. NEW_BRIDGE="$1"; shift
  243. NEW_IP_CMD="$@"
  244. if [[ "${NEW_BRIDGE}" != "" ]]; then
  245. # Getting commands for "ip"
  246. IP_CMDS_VARIABLE="${NEW_BRIDGE//[.]/_}_IP"
  247. IP_CMDS_VARIABLE="${IP_CMDS_VARIABLE}"
  248. eval "${IP_CMDS_VARIABLE}[\${#${IP_CMDS_VARIABLE}}]=\"$NEW_IP_CMD\""
  249. fi
  250. ;;
  251. delipcmd)
  252. NEWCONFIG=1 # we need to update the config after the command
  253. NEW_BRIDGE="$1"; shift
  254. NEW_IP_CMD="$@"
  255. if [[ "${NEW_BRIDGE}" != "" ]]; then
  256. IP_CMDS_VARIABLE="${NEW_BRIDGE//[.]/_}_IP"
  257. IP_CMDS_VARIABLE="${IP_CMDS_VARIABLE}"
  258. i=0
  259. CMD_founded=0
  260. for IP_CMD in "${!IP_CMDS_VARIABLE}"; do
  261. if [[ "$IP_CMD" = "$NEW_IP_CMD" ]]; then
  262. CMD_founded=1
  263. else
  264. TMP[$i]=$IP_CMD
  265. (( i++ ))
  266. fi
  267. done
  268. if [[ $CMD_founded -eq 0 ]]; then
  269. eerror "There's no such command"
  270. exit -1
  271. fi
  272. i=0
  273. for IP_CMD in "${!TMP}"; do
  274. IP_CMDS_VARIABLE[$i]=$IP_CMD
  275. (( i++ ))
  276. done
  277. #eval "${IP_CMDS_VARIABLE}[\${#${IP_CMDS_VARIABLE}}]=\"$NEW_IP_CMD\""
  278. #echo $IP_CMDS_VARIABLE
  279. fi ;;
  280. fix) #fix all interfaces to config state
  281. #brctl addif bond0 eth2
  282. if [[ "$IPW_DEBUG" -ge "2" ]]; then
  283. cat "$IPW_CONFIG_PATH" > /tmp/ipw.conf-fix.$(date +'%Y%m%d%H%M%S')
  284. fi
  285. if [[ "$IPW_CONFIG_PATH" != "/dev/null" ]]; then
  286. if [[ "$(cat $IPW_CONFIG_PATH 2>/dev/null)" = "" ]]; then
  287. eerror "Empty config file"
  288. exit -1
  289. fi
  290. fi
  291. #GETTING INFORMATION ABOUT LXC INTERFACES IN BRIDGES
  292. if [[ "$LXC_DIR" != "" ]]; then
  293. LXC_BRIDGE_SLAVES=($(cat "$LXC_DIR"/*/config 2>/dev/null | tr -d " \t" | awk -F '=' '{if($1=="lxc.network.link") {BRIDGE=$2}; if($1=="lxc.network.veth.pair") {if(BRIDGE!="") {print $2":"BRIDGE; BRIDGE=""}} }'))
  294. fi
  295. #REMOVING UNNECESSARY D1Q
  296. OLD_D1Q_IFACES="`cat /sys/class/net/bonding_masters`"
  297. for OLD_D1Q_IFACE in ${OLD_D1Q_IFACES[@]}; do
  298. # Removing trunk bridge (like "bond0br")
  299. TRUNK_BRIDGE_IS_USED=0
  300. for D1Q_IFACE in ${D1Q_IFACES[@]}; do
  301. if [[ "$D1Q_IFACE" == "$OLD_D1Q_IFACE" ]]; then
  302. TRUNK_BRIDGE_IS_USED=1
  303. break
  304. fi
  305. done
  306. if [[ "${SKIP_BRIDGES_MAP[${OLD_D1Q_IFACE}br]}" = "1" ]]; then
  307. TRUNK_BRIDGE_IS_USED=1
  308. fi
  309. if [[ "$TRUNK_BRIDGE_IS_USED" -eq 0 ]]; then
  310. OLD_TRUNK_BRIDGE="$OLD_D1Q_IFACE"br
  311. if [[ -d /sys/class/net/"$OLD_TRUNK_BRIDGE" ]]; then
  312. ip link set "$OLD_D1Q_IFACE" nomaster 2>/dev/null
  313. ip link delete "$OLD_TRUNK_BRIDGE"
  314. fi
  315. fi
  316. # Removing slaves and the interface itself
  317. D1Q_IS_USED=0
  318. OLD_SLAVES="`cat /sys/class/net/"$OLD_D1Q_IFACE"/bonding/slaves`"
  319. for D1Q_IFACE in ${D1Q_IFACES[@]}; do
  320. if [[ "$D1Q_IFACE" == "$OLD_D1Q_IFACE" ]]; then #let's kick out useless slaves
  321. SLAVES_VARIABLE="${D1Q_IFACE}_SLAVES"
  322. SLAVES_VARIABLE="${SLAVES_VARIABLE//[.]/_}[@]"
  323. for OLD_SLAVE in ${OLD_SLAVES[@]}; do
  324. SLAVE_IS_USED=0
  325. for SLAVE in "${!SLAVES_VARIABLE}"; do
  326. if [[ "$SLAVE" == "$OLD_SLAVE" ]]; then
  327. SLAVE_IS_USED=1
  328. break;
  329. fi
  330. done
  331. if [[ "$SLAVE_IS_USED" == 0 ]]; then
  332. echo "-$OLD_SLAVE" > /sys/class/net/"$OLD_D1Q_IFACE"/bonding/slaves
  333. fi
  334. done
  335. D1Q_IS_USED=1
  336. break;
  337. fi
  338. done
  339. if [[ "$D1Q_IS_USED" == 0 ]]; then #let's kick out useless d1q
  340. echo "-$OLD_D1Q_IFACE" > /sys/class/net/bonding_masters
  341. fi
  342. done
  343. #REMEMBERING REQUIRED INTERFACES
  344. declare -A REQUIRED_FULLNAME_HASH
  345. declare -A REQUIRED_BRNAME_HASH
  346. declare -A REQUIRED_IFACENAME_HASH
  347. for D1Q_IFACE_TMP in ${D1Q_IFACES[@]}; do #we should keep slave ifaces
  348. REQUIRED_BRNAME_HASH["${D1Q_IFACE_TMP}br"]="${D1Q_IFACE_TMP}br"
  349. REQUIRED_IFACENAME_HASH["$D1Q_IFACE_TMP"]="$D1Q_IFACE_TMP"
  350. VLAN_N_BRIDGE_VARIABLE="${D1Q_IFACE_TMP}_VLAN_N_BRIDGES"
  351. VLAN_N_BRIDGE_VARIABLE="${VLAN_N_BRIDGE_VARIABLE//[.]/_}[@]"
  352. for VLAN_N_BRIDGE in "${!VLAN_N_BRIDGE_VARIABLE}"; do
  353. parse_vlan_subvlan_bridge "${VLAN_N_BRIDGE}"
  354. REQUIRED_FULLNAME_HASH["$D1Q_IFACE_TMP"."$VLAN_N_BRIDGE"]="$D1Q_IFACE_TMP"."$VLAN_N_BRIDGE"
  355. if [[ "$BRNAME" != "" ]]; then
  356. REQUIRED_BRNAME_HASH["$BRNAME"]="$BRNAME"
  357. fi
  358. if [[ "$VLANNAME" != "" ]]; then
  359. REQUIRED_IFACENAME_HASH["$VLANNAME"]="$VLANNAME"
  360. REQUIRED_IFACENAME_HASH["$D1Q_IFACE_TMP"."$VLAN"]="$D1Q_IFACE_TMP"."$VLAN"
  361. fi
  362. done
  363. done
  364. for LXCIF_N_BRIDGE in ${LXC_BRIDGE_SLAVES[@]}; do
  365. REQUIRED_FULLNAME_HASH["$LXCIF_N_BRIDGE"]="$LXCIF_N_BRIDGE"
  366. done
  367. #CONFIGURING AND REMEMBERING ACCESS INTERFACES (NOT D1Q)
  368. for ACCESS_IFACE in ${ACCESS_IFACES[@]}; do
  369. oldIFS="$IFS"; IFS=":"
  370. WORDS=(${ACCESS_IFACE})
  371. IFS="$oldIFS"
  372. IFACE="${WORDS[0]}"
  373. BRNAME="${WORDS[1]}"
  374. if [[ "$BRNAME" != "" ]]; then
  375. REQUIRED_BRNAME_HASH["$BRNAME"]="$BRNAME"
  376. if ! iface_isexists "$BRNAME"; then
  377. ip link add "$BRNAME" type bridge
  378. ip link set dev "$BRNAME" mtu "$DEFAULT_MTU"
  379. ip link set dev "$BRNAME" up
  380. fi
  381. ip link set "$IFACE" master "$BRNAME"
  382. ip_cmds "$BRNAME"
  383. fi
  384. REQUIRED_IFACENAME_HASH["$IFACE"]="$IFACE"
  385. ip_cmds "$IFACE"
  386. done
  387. #REMOVING UNNECESSARY BRIDGES AND VLANS
  388. OLD_VLAN_N_BRIDGES=(`get_vlan_n_bridges`)
  389. for LINE in ${OLD_VLAN_N_BRIDGES[@]}; do
  390. #echo ITERATION
  391. parse_vlan_subvlan_bridge "$LINE"
  392. OLD_BRNAME="$BRNAME"
  393. OLD_VLANNAME="$VLANNAME"
  394. IS_SLAVE=0
  395. BRIDGE_IN_USE=0
  396. IFACE_IN_USE=0
  397. VLAN_N_BRIDGE_IN_USE=0
  398. if [[ "${REQUIRED_FULLNAME_HASH[$LINE]}" != "" ]] || [[ "${SKIP_BRIDGES_MAP[$OLD_BRNAME]}" = "1" ]]; then
  399. BRIDGE_IN_USE=1
  400. IFACE_IN_USE=1
  401. VLAN_N_BRIDGE_IN_USE=1
  402. else
  403. [[ "$OLD_BRNAME" != "" ]] &&
  404. if [[ "${REQUIRED_BRNAME_HASH[$OLD_BRNAME]}" != "" ]]; then
  405. BRIDGE_IN_USE=1
  406. fi
  407. [[ "$OLD_VLANNAME" != "" ]] &&
  408. if [[ "${REQUIRED_IFACENAME_HASH[$OLD_VLANNAME]}" != "" ]]; then
  409. IFACE_IN_USE=1
  410. fi
  411. fi
  412. if [[ "$BRIDGE_IN_USE" = 0 ]]; then
  413. [[ "$OLD_BRNAME" != '' ]] &&
  414. ip link delete "$OLD_BRNAME"
  415. fi
  416. if [[ "$IFACE_IN_USE" = 0 ]]; then
  417. if [[ "$OLD_VLANNAME" != '' ]]; then
  418. ip link set "$OLD_VLANNAME" nomaster
  419. ip link delete "$OLD_VLANNAME"
  420. fi
  421. fi
  422. done
  423. #CREATING OF NECESSARY D1Q
  424. for D1Q_IFACE in ${D1Q_IFACES[@]}; do
  425. # Fixing bond-ifaces if exists
  426. SLAVES_VARIABLE="${D1Q_IFACE}_SLAVES"
  427. SLAVES_VARIABLE="${SLAVES_VARIABLE//[.]/_}[@]"
  428. MODE_VARIABLE="${D1Q_IFACE}_MODE"
  429. MODE="${!MODE_VARIABLE}"; [[ "$MODE" = "" ]] && MODE="$DEFAULT_BONDING_MODE"
  430. D1Q_EXISTS=0
  431. for OLD_D1Q_IFACE in ${OLD_D1Q_IFACES[@]}; do
  432. if [[ "$D1Q_IFACE" == "$OLD_D1Q_IFACE" ]]; then #it's here. Let's fix it.
  433. OLD_SLAVES="`cat /sys/class/net/"$OLD_D1Q_IFACE"/bonding/slaves`"
  434. OLD_BONDING_MODE=(`cat /sys/class/net/"$OLD_D1Q_IFACE"/bonding/mode`)
  435. if [ "${OLD_BONDING_MODE[0]}" != "${MODE}" -a "${OLD_BONDING_MODE[1]}" != "${MODE}" ]; then
  436. for OLD_SLAVE in ${OLD_SLAVES[@]}; do
  437. echo "-$OLD_SLAVE" > /sys/class/net/"$OLD_D1Q_IFACE"/bonding/slaves
  438. done
  439. ip link set dev "$OLD_D1Q_IFACE" down
  440. echo "$MODE" > /sys/class/net/"$OLD_D1Q_IFACE"/bonding/mode
  441. OLD_SLAVES=()
  442. fi
  443. for SLAVE in "${!SLAVES_VARIABLE}"; do
  444. SLAVE_EXISTS=0
  445. for OLD_SLAVE in ${OLD_SLAVES[@]}; do
  446. if [[ "$SLAVE" == "$OLD_SLAVE" ]]; then
  447. SLAVE_EXISTS=1
  448. break;
  449. fi
  450. done
  451. if [[ "$SLAVE_EXISTS" == 0 ]]; then
  452. ip link set dev "$SLAVE" down #enslaved int should be shutted down
  453. echo "+$SLAVE" > /sys/class/net/"$D1Q_IFACE"/bonding/slaves
  454. fi
  455. done
  456. D1Q_EXISTS=1
  457. break;
  458. fi
  459. done
  460. # Creating bond-ifaces
  461. if [[ "$D1Q_EXISTS" == 0 ]]; then #make all
  462. echo "+$D1Q_IFACE" > /sys/class/net/bonding_masters 2>/dev/null
  463. ip link set dev "$D1Q_IFACE" mtu "$DEFAULT_MTU"
  464. if [[ -d /sys/class/net/"$D1Q_IFACE"/bonding ]]; then
  465. echo "$MODE" > /sys/class/net/"$D1Q_IFACE"/bonding/mode
  466. fi
  467. for SLAVE in "${!SLAVES_VARIABLE}"; do
  468. ip link set dev "$SLAVE" down #enslaved int should be shutted down
  469. echo "+$SLAVE" > /sys/class/net/"$D1Q_IFACE"/bonding/slaves
  470. done
  471. fi
  472. ip link set dev "$D1Q_IFACE" up
  473. for SLAVE in "${!SLAVES_VARIABLE}"; do #slave starts after bond
  474. ip link set dev "$SLAVE" mtu "$DEFAULT_MTU"
  475. ip link set dev "$SLAVE" up
  476. done
  477. # Creating trunk bridge (like "bond0br")
  478. TRUNK_BRIDGE="$D1Q_IFACE"br
  479. if ! [[ -d /sys/class/net/"$TRUNK_BRIDGE" ]]; then
  480. ip link add "$TRUNK_BRIDGE" type bridge
  481. echo "$BRIDGE_FORWARD_DELAY" > /sys/devices/virtual/net/"$TRUNK_BRIDGE"/bridge/forward_delay
  482. ip link set dev "$TRUNK_BRIDGE" mtu "$DEFAULT_MTU"
  483. ip link set dev "$TRUNK_BRIDGE" up
  484. ip link set "$D1Q_IFACE" master "$TRUNK_BRIDGE"
  485. fi
  486. # Creating necessary bridges and VLANs
  487. VLAN_N_BRIDGE_VARIABLE="${D1Q_IFACE}_VLAN_N_BRIDGES"
  488. VLAN_N_BRIDGE_VARIABLE="${VLAN_N_BRIDGE_VARIABLE//[.]/_}[@]"
  489. for VLAN_N_BRIDGE in "${!VLAN_N_BRIDGE_VARIABLE}"; do
  490. parse_vlan_subvlan_bridge "${VLAN_N_BRIDGE}"
  491. FULL_VLAN_NAME="$D1Q_IFACE"."$VLANNAME"
  492. #VLAN STUFF
  493. if [[ "$VLAN" != "" ]]; then
  494. if ! iface_isexists "$FULL_VLAN_NAME"; then #should we create a new vlan?
  495. if [[ "$SUBVLAN" != "" ]]; then #is it subvlan?
  496. FULL_PARVLAN_NAME="$D1Q_IFACE"."$VLAN"
  497. if ! iface_isexists "$FULL_PARVLAN_NAME"; then #should we create a new parent vlan?
  498. ip link add link "$D1Q_IFACE" name "$FULL_PARVLAN_NAME" type vlan id "$VLAN" #vlan in bond
  499. ip link set dev "$FULL_PARVLAN_NAME" mtu "$DEFAULT_MTU"
  500. ip link set dev "$FULL_PARVLAN_NAME" up
  501. fi
  502. ip link add link "$FULL_PARVLAN_NAME" name "$FULL_VLAN_NAME" type vlan id "$SUBVLAN" #subvlan in vlan
  503. #ip link set dev "$FULL_VLAN_NAME" mtu "$(( $DEFAULT_MTU - 4 ))"
  504. ip link set dev "$FULL_VLAN_NAME" mtu 1496
  505. ip link set dev "$FULL_VLAN_NAME" up
  506. else
  507. ip link add link "$D1Q_IFACE" name "$FULL_VLAN_NAME" type vlan id "$VLANNAME" #vlan in bond
  508. ip link set dev "$FULL_VLAN_NAME" mtu "$DEFAULT_MTU"
  509. ip link set dev "$FULL_VLAN_NAME" up
  510. fi
  511. fi
  512. ip_cmds "$FULL_VLAN_NAME"
  513. fi
  514. #BRIDGE STUFF
  515. if [[ "$BRNAME" != "" ]]; then
  516. if ! iface_isexists "$BRNAME"; then #do this bridge exists?
  517. ip link add "$BRNAME" type bridge
  518. echo "$BRIDGE_FORWARD_DELAY" > /sys/devices/virtual/net/"$BRNAME"/bridge/forward_delay
  519. ip link set dev "$BRNAME" mtu "$DEFAULT_MTU"
  520. ip link set dev "$BRNAME" up
  521. fi
  522. if [[ "$VLAN" != "" ]]; then
  523. OLD_BRNAME="`get_brname_byslave "$FULL_VLAN_NAME"`"
  524. if [[ "$OLD_BRNAME" = "" ]]; then #is this vlan have been already enslaved?
  525. ip link set "$FULL_VLAN_NAME" master "$BRNAME"
  526. else
  527. if [[ "$BRNAME" != "$OLD_BRNAME" ]]; then
  528. ip link set "$FULL_VLAN_NAME" nomaster
  529. ip link set "$FULL_VLAN_NAME" master "$BRNAME"
  530. fi
  531. fi
  532. fi
  533. ip_cmds "$BRNAME"
  534. fi
  535. done
  536. done
  537. if [[ "$LXC_DIR" != "" ]]; then
  538. # CREATING LXC IFACES
  539. #for CONTAINER in $(cat "$LXC_DIR"/*/config | tr -d " \t" | awk -F '=' '{if($1=="lxc.utsname") print $2}'); do
  540. for CONTAINER in $(ls "$LXC_DIR"/); do
  541. CONTAINER_STATUS=$(lxc-info -n "$CONTAINER" 2>/dev/null | awk '{if ($1 == "State:") { print $2; exit }}')
  542. # Skip the container if it's not running on this host
  543. [[ "$CONTAINER_STATUS" != "RUNNING" ]] &&
  544. continue
  545. # Getting an already set up interfaces
  546. unset CONTAINER_CURRENT_IFACES
  547. declare -A CONTAINER_CURRENT_IFACES
  548. #for IFACE in $(lxc-info -n "$CONTAINER" | awk '{if ($1 == "Link:") print $2 }'); do
  549. for IFACE in $(lxc-attach -n "$CONTAINER" -- ls /sys/devices/virtual/net/); do
  550. CONTAINER_CURRENT_IFACES["$IFACE"]="$IFACE"
  551. done
  552. # Getting an interfaces that _should_ be set up
  553. CONTAINER_CONFIG_IFACES=($(cat "$LXC_DIR"/"$CONTAINER"/config | tr -d " \t" | awk -F '=' '{if($1=="lxc.network.veth.pair") {HNAME=$2}; if($1=="lxc.network.name") {GNAME=$2}; if ($1 == "lxc.network.link") {BRIDGE=$2}; if ($1 == "lxc.network.type" && HNAME!="" && GNAME!="") {print HNAME":"GNAME":"BRIDGE; HNAME=""; GNAME=""; BRIDGE=""} } END { if(HNAME!="" && GNAME!="") print HNAME":"GNAME":"BRIDGE }'))
  554. LXC_PID=''
  555. for CONTAINER_IF_N_BRIDGE in ${CONTAINER_CONFIG_IFACES[@]}; do
  556. WORDS=( ${CONTAINER_IF_N_BRIDGE//[:]/ } )
  557. HNAME="${WORDS[0]}"
  558. GNAME="${WORDS[1]}"
  559. BRIDGE="${WORDS[2]}"
  560. # Skip if the interface is already exists
  561. [[ "${CONTAINER_CURRENT_IFACES[$GNAME]}" != '' ]] &&
  562. continue
  563. # Getting a pid of container's init
  564. [[ "$CONTAINER_PID" == '' ]] &&
  565. CONTAINER_PID=$(lxc-info -p -n "$CONTAINER" | awk '{ print $2 }')
  566. ip link add name "$HNAME" type veth peer name ".c$GNAME" &&
  567. lxc-attach -n "$CONTAINER" ifdown "$GNAME"
  568. ip link set "$HNAME" mtu "$DEFAULT_MTU"
  569. ip link set "$HNAME" up
  570. ip link set ".c$GNAME" netns "$CONTAINER_PID"
  571. lxc-attach -n "$CONTAINER" ip link set ".c$GNAME" name "$GNAME"
  572. lxc-attach -n "$CONTAINER" ip link set "$GNAME" up
  573. lxc-attach -n "$CONTAINER" ifup "$GNAME"
  574. [[ "$BRIDGE" != '' ]] &&
  575. [[ "$IPW_FAST" -ne 0 ]] &&
  576. brctl addif "$BRIDGE" "$HNAME"
  577. done
  578. CONTAINER_PID=""
  579. done
  580. [[ "$IPW_FAST" -eq 0 ]] &&
  581. # ADDING LXC IFACES TO BRIDGES IF REQUIRED
  582. for LXCIF_N_BRIDGE in ${LXC_BRIDGE_SLAVES[@]}; do
  583. parse_vlan_subvlan_bridge "$LXCIF_N_BRIDGE"
  584. brctl addif "$BRNAME" "$VLANNAME" 2>/dev/null
  585. done
  586. fi
  587. ;;
  588. *)
  589. ;;
  590. esac
  591. newconfig_open
  592. newconfig_write "#"
  593. newconfig_write ""
  594. newconfig_write "D1Q_IFACES=("
  595. for D1Q_IFACE in ${D1Q_IFACES[@]}; do
  596. newconfig_write " $D1Q_IFACE"
  597. newconfig_push 128 "${D1Q_IFACE}_SLAVES=("
  598. haveaslave=0
  599. SLAVES_VARIABLE="${D1Q_IFACE}_SLAVES"
  600. SLAVES_VARIABLE="${SLAVES_VARIABLE//[.]/_}[@]"
  601. for SLAVE in "${!SLAVES_VARIABLE}"; do
  602. newconfig_push 128 " $SLAVE";
  603. haveaslave=1
  604. done
  605. newconfig_push 128 ")"
  606. # If there're no slaves then don't write anything about them
  607. [[ $haveaslave -ne 0 ]] && newconfig_pushpopall 1 128 || newconfig_popall 128
  608. VLAN_N_BRIDGE_VARIABLE="${D1Q_IFACE}_VLAN_N_BRIDGES"
  609. VLAN_N_BRIDGE_VARIABLE="${VLAN_N_BRIDGE_VARIABLE//[.]/_}[@]"
  610. newconfig_push 1 "${D1Q_IFACE}_VLAN_N_BRIGES=("
  611. for VLAN_N_BRIDGE in "${!VLAN_N_BRIDGE_VARIABLE}"; do
  612. newconfig_push 1 " ${VLAN_N_BRIDGE}"
  613. parse_vlan_subvlan_bridge "${VLAN_N_BRIDGE}"
  614. # Checking if no "vlan(.subvlan)?" is set
  615. if [[ "${BRNAME}" != "" ]]; then
  616. #echo $BRNAME
  617. # Getting commands for "ip"
  618. IP_CMDS_VARIABLE="${BRNAME//[.]/_}_IP"
  619. newconfig_push 128 "${IP_CMDS_VARIABLE}=("
  620. IP_CMDS_VARIABLE="${IP_CMDS_VARIABLE}[@]"
  621. hasanIP_CMD=0
  622. for IP_CMD in "${!IP_CMDS_VARIABLE}"; do
  623. newconfig_push 128 " \"$IP_CMD\""
  624. #echo ip $IP_CMD dev $BRNAME
  625. hasanIP_CMD=1
  626. done
  627. newconfig_push 128 ")"
  628. newconfig_push 128 ""
  629. [[ $hasanIP_CMD -ne 0 ]] && newconfig_pushpopall 2 128 || newconfig_popall 128
  630. else
  631. # Getting commands for "ip"
  632. #echo OK
  633. IP_CMDS_VARIABLE="vlan${VLANNAME//[.]/_}_IP"
  634. newconfig_push 128 "${IP_CMDS_VARIABLE}=("
  635. IP_CMDS_VARIABLE="${IP_CMDS_VARIABLE}[@]"
  636. hasanIP_CMD=0
  637. for IP_CMD in "${!IP_CMDS_VARIABLE}"; do
  638. newconfig_push 128 " \"$IP_CMD\""
  639. #echo ip $IP_CMD dev $VLANNAME
  640. hasanIP_CMD=1
  641. done
  642. newconfig_push 128 ")"
  643. newconfig_push 128 ""
  644. [[ $hasanIP_CMD -ne 0 ]] && newconfig_pushpopall 2 128 || newconfig_popall 128
  645. fi
  646. printf "br: %-16s vlan:%5s subvlan:%5s\n" "$BRNAME" "$VLAN" "$SUBVLAN"
  647. done
  648. newconfig_push 1 ")"
  649. done
  650. for ACCESS_IFACE in ${ACCESS_IFACES[@]}; do
  651. oldIFS="$IFS"; IFS=":"
  652. WORDS=(${ACCESS_IFACE})
  653. IFS="$oldIFS"
  654. IFACE="${WORDS[0]}"
  655. BRNAME="${WORDS[1]}"
  656. printf "access: %-12s bridge: %-8s\n" "$IFACE" "$BRNAME"
  657. done
  658. newconfig_write ")"
  659. newconfig_popallwrite 1
  660. newconfig_popallwrite 2
  661. newconfig_popallwrite 3
  662. #[[ $NEWCONFIG -ne 0 ]] && newconfig_commit
  663. exit 0