]> git.ipfire.org Git - people/ms/network.git/blobdiff - src/hooks/ports/vlan
vlan: Add support for 802.1ad (QinQ)
[people/ms/network.git] / src / hooks / ports / vlan
index 344361484fbceb7a6469f6c7630e2b4036efb180..af563eed4bfa7b3ce9df31dd2c555411dba4de4b 100644 (file)
 
 . /usr/lib/network/header-port
 
-HOOK_SETTINGS="HOOK ADDRESS PARENT_DEVICE TAG"
+HOOK_SETTINGS=(
+       "ADDRESS"
+       "ID"
+       "PARENT_PORT"
+       "PROTOCOL"
+)
 
-PORT_PARENTS_VAR="PARENT"
+# Set the default to 802.1Q
+DEFAULT_PROTOCOL="${VLAN_SUPPORTED_PROTOCOLS[0]}"
+
+PORT_PARENTS_VAR="PARENT_PORT"
 
 hook_check_settings() {
-       assert isset PARENT_DEVICE
-       assert isinteger TAG
+       assert ismac ADDRESS
+       assert isset PARENT_PORT
 
-       if isset ADDRESS; then
-               assert ismac ADDRESS
-       fi
+       assert isset PROTOCOL
+       assert vlan_supported_protocol "${PROTOCOL}"
 
-       if [ ${TAG} -gt 4096 ]; then
-               error "TAG is greater than 4096."
-               exit ${EXIT_ERROR}
-       fi
+       assert isinteger ID
+       assert vlan_valid_id "${ID}"
+}
 
-       local reserved
-       for reserved in 0 4095; do
-               if [ "${TAG}" = "${reserved}" ]; then
-                       error "TAG=${reserved} is reserved."
-                       exit ${EXIT_ERROR}
-               fi
-       done
+hook_find_port_name() {
+       assert isset ID
+       assert isset PARENT_PORT
+
+       print "${PARENT_PORT}${VLAN_PORT_INTERFIX}${ID}"
 }
 
-hook_new() {
+hook_parse_cmdline() {
        while [ $# -gt 0 ]; do
                case "${1}" in
-                       --parent-device=*)
-                               PARENT_DEVICE=$(cli_get_val ${1})
-                               ;;
                        --address=*)
-                               ADDRESS=$(cli_get_val ${1})
+                               ADDRESS=$(cli_get_val "${1}")
+
+                               # Validate address
+                               if ! mac_is_valid "${ADDRESS}"; then
+                                       error "Invalid MAC address given: ${ADDRESS}"
+                                       return ${EXIT_CONF_ERROR}
+                               fi
                                ;;
-                       --tag=*)
-                               TAG=$(cli_get_val ${1})
+                       --id=*)
+                               ID=$(cli_get_val "${1}")
+
+                               # Validate VLAN ID
+                               if ! vlan_valid_id "${ID}"; then
+                                       error "Invalid VLAN ID: ${ID}"
+                                       return ${EXIT_CONF_ERROR}
+                               fi
                                ;;
-                       *)
-                               warning "Unknown argument '${1}'"
+                       --port=*)
+                               PARENT_PORT=$(cli_get_val "${1}")
+
+                               # Check if PARENT_PORT exists
+                               if ! port_exists "${PARENT_PORT}"; then
+                                       error "Port '${PARENT_PORT}' does not exist"
+                                       return ${EXIT_CONF_ERROR}
+                               fi
                                ;;
-               esac
-               shift
-       done
-
-       local port="${PARENT_DEVICE}${VLAN_PORT_INTERFIX}${TAG}"
-
-       port_settings_write "${port}" ${HOOK_SETTINGS}
-
-       exit ${EXIT_OK}
-}
-
-hook_edit() {
-       local port=${1}
-       assert isset port
-       shift
-
-       port_settings_read "${port}" ${HOOK_SETTINGS}
-
-       while [ $# -gt 0 ]; do
-               case "${1}" in
-                       --address=*)
-                               ADDRESS=$(cli_get_val ${1})
+                       --protocol=*)
+                               PROTOCOL="$(cli_get_val "${1}")"
+
+                               # Check if PROTOCOL is supported
+                               if ! vlan_supported_protocol "${PROTOCOL}"; then
+                                       error "Protocol '${PROTOCOL}' is not supported"
+                                       error "Choose one of ${VLAN_SUPPORTED_PROTOCOLS[*]}"
+                                       return ${EXIT_CONF_ERROR}
+                               fi
                                ;;
                        *)
-                               warning "Unknown argument '${1}'"
+                               error "Unknown argument '${1}'"
+                               return ${EXIT_CONF_ERROR}
                                ;;
                esac
                shift
        done
 
-       port_settings_write "${port}" ${HOOK_SETTINGS}
-
-       exit ${EXIT_OK} 
+       # Generate a random MAC address if none given
+       if ! isset ADDRESS; then
+               ADDRESS="$(mac_generate)"
+       fi
 }
 
 hook_create() {
@@ -104,12 +112,33 @@ hook_create() {
        device_exists "${port}" && exit ${EXIT_OK}
 
        # Read configruation
-       port_settings_read "${port}" ${HOOK_SETTINGS}
+       if ! port_settings_read "${port}"; then
+               return ${EXIT_ERROR}
+       fi
+
+       # Check if the parent port exists
+       if ! port_exists "${PARENT_PORT}"; then
+               error "Port '${PARENT_PORT}' does not exist"
+               return ${EXIT_ERROR}
+       fi
+
+       # Create the partent port first
+       if ! port_create "${PARENT_PORT}"; then
+               error "Could not bring up parent port: ${PARENT_PORT}"
+               return ${EXIT_ERROR}
+       fi
 
        # Create the VLAN device
-       vlan_create "${port}" "${PARENT_DEVICE}" "${TAG}" "${ADDRESS}"
+       if ! vlan_create "${port}" \
+                       --address="${ADDRESS}" \
+                       --id="${ID}" \
+                       --parent="${PARENT_PORT}" \
+                       --protocol="${PROTOCOL}"; then
+               error "Could not create port: ${port}"
+               return ${EXIT_ERROR}
+       fi
 
-       exit ${EXIT_OK}
+       return ${EXIT_OK}
 }
 
 hook_remove() {