ipw 20 KB

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