ipw 21 KB

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