qemu-hook 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #!/bin/sh -e
  2. #
  3. # Libvirt qemu hook to magically connect VM bridge interfaces to desired untagged Vlan
  4. #
  5. # IF
  6. # * the VM interface if configured to be connected to a bridge,
  7. # * the bridge is configured to be vlan aware (vlan_filtering = 1)
  8. # * the VM interface name ends with _vXXXX with XXXX being a one to four
  9. # digit number
  10. # the interface will be configured as an untagged port connected to vlan XXXX.
  11. #
  12. # See <man bridge> for more details about vlan aware bridges.
  13. #
  14. # Maximilian Wilhelm <max@sdn.clinic>
  15. # -- Wed, 31 Aug 2016 20:48:02 +0200
  16. my_name="qemu-magic"
  17. # We only care for the "started" event.
  18. if [ "$2" != 'started' ]; then
  19. exit 0
  20. fi
  21. if ! which xmlstarlet >/dev/null 2>/dev/null; then
  22. logger -t "${my_name}" "ERROR: xmlstarlet not found. Dying of shame."
  23. echo "${my_name}: ERROR: xmlstarlet not found. Dying of shame." >&2
  24. exit 1
  25. fi
  26. xmlstarlet sel -t -m '//interface[@type="bridge"]' -v 'concat(target/@dev, " ", source/@bridge)' --nl | while read iface bridge; do
  27. if [ ! -d "/sys/class/net/${bridge}/bridge" ]; then
  28. logger -t "${my_name}" "Bridge \"${bridge}\" for iface \"${iface}\" doesn't exist or isn't a bridge."
  29. exit 2
  30. fi
  31. #
  32. # Check if this kernel supports vlan-aware bridges and if ${bridge} is one
  33. vlan_filtering=0
  34. if [ -f "/sys/class/net/${bridge}/bridge/vlan_filtering" ]; then
  35. vlan_filtering=$(cat "/sys/class/net/${bridge}/bridge/vlan_filtering")
  36. fi
  37. # If the interface is named *_vXXXX, with XXXX being a 1-4 digit number
  38. # we assume that this iface should be connected to Vlan XXXX with
  39. # an untagged port.
  40. vlan_id=$(echo ${iface} | grep -o '_v[0-9]\{1,4\}$' | cut -c3-)
  41. # If vlan filtering is activated and we found a vlan id, kindly do the needful.
  42. if [ "${vlan_filtering}" -a "${vlan_id}" ]; then
  43. # Remove association with vlan 1 and add association with
  44. # vlan $vlan_id with packages being sent out untagged and
  45. # untagged ingress packets get tagged accordingly.
  46. bridge vlan del vid 1 dev "${iface}"
  47. bridge vlan add vid "${vlan_id}" dev "${iface}" pvid untagged
  48. logger -t "${my_name}" "Configured untagged pvid ${vlan_id} for ${iface} in bridge ${bridge}."
  49. # If vlan filtering isn't activated or supported but we found a vlan id,
  50. # this probably is an error!
  51. elif [ ! "${vlan_filtering}" -a "${vlan_id}" ]; then
  52. logger -t "${my_name}" -p user.error "ERROR: Should configure untagged pvid ${vlan_id} for ${iface} in bridge ${bridge}, but bridge does not support vlan filtering!"
  53. fi
  54. # We dont' care about "no vlan filtering AND no vlan id" as well as "vlan filtering AND no vlan id"
  55. # If there is an configuration stanza in /etc/network/interfaces
  56. # for this interfaces, we try to get it up and running. Proceed
  57. # with fingers crossed.
  58. if grep -q "^iface\s\+${iface}" /etc/network/interfaces; then
  59. if ifup $iface; then
  60. logger -t "${my_name}" "ifup'ed ${iface}."
  61. else
  62. logger -t "${my_name}" -p user.error "ifup ${iface} FAILED."
  63. fi
  64. fi
  65. done