From f7922f6d21feaa4e71973086f6ca16b56cf6ca11 Mon Sep 17 00:00:00 2001 From: Andrea F Date: Sun, 30 Oct 2016 13:17:31 +0100 Subject: [PATCH] [fix] LOCAL_IFNAME and GUEST_IFNAME max name size A bug fix for the automatic creation logic of the LOCAL_IFNAME and GUEST_IFNAME vars values. 1. Problem description Pipework always automatically computes the value of the $GUEST_IFNAME var. This var is used to define the name of the guest interface before it's added to the guest's NS and it's subsequently renamed to the value of the $CONTAINER_IFNAME. The actual value is computed as follow: - GUEST_IFNAME=v${CONTAINER_IFNAME}pg${NSPID} if the IFTYPE is "bridge" - GUEST_IFNAME=ph$NSPID$CONTAINER_IFNAME if the $IFTYPE is "phys" - GUEST_IFNAME=du$NSPID$CONTAINER_IFNAME if the $IFTYPE is "dummy" However, specifying a long but valid $CONTAINER_IFNAME (up to i.e. IF_NAMSIZ chars in linux) does rise and error, because the concatenated string for the $GUEST_IFNAME var will be then larger than the maximum allowed value (again IF_NAMSIZ in the linux case). The same issue arises in this scenario if a -i option isn't passed to pipework to specify a valid $LOCAL_IFNAME, as the value for this var is computed in the exact same way described above (using "pg" instead of "pl" in the concatenated string) 2. Example # pipework br_pub_5 -i pub_lan_7 base 192.168.4.27/24 Error: argument "vpub_lan_7pl28223" is wrong: "name" too long 3. Fix To fix this issue, the algorith to compute the value of $GUEST_IFNAME and $LOCAL_IFNAME has been modified in this way: - a $IF_NAME_MAX_SIZE constant is added to the script to define the max size for a valid network interface name. I'm unaware of a multi-platform, reliable way to autodetect this value, so I've used a constant to store it - the name of the interface is computed as: veth${NSPID}_${RANDOM_STRING} for the $LOCAL_IFNAME var (if -i isn't specified) - the name of the interface is computed as: teth${NSPID}_${RANDOM_STRING} for the $GUEST_IFNAME var - in both cases, the lenght of $LOCAL_IFNAME and $GUEST_IFNAME will be guaranteed lower than the $IF_NAME_MAX_SIZE 4. ToDo The $GUEST_IFNAME var is automatically computed also if the $IFTYPE var is "ipoib". The same issue could potentially arise if $IFNAME is as long as IF_NAMSIZ, as the $GUEST_IFNAME is computed longer than $IFTYPE. However I'm unsure about the interface naming requirements for this networking layer and cannot test it. So this case should be checked and the automatic value should be computed accordingly --- pipework | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pipework b/pipework index bd51fac..479c6a2 100755 --- a/pipework +++ b/pipework @@ -3,6 +3,12 @@ # (https://google-styleguide.googlecode.com/svn/trunk/shell.xml) set -e +# default max size for interface names (cfr. IFNAMSIZ) +readonly IF_MAX_NAME_SIZE=15 + +# Random string used to compute interface names +readonly RAND_STRING=`for i in {0..16}; do rndval+=$(printf "%x" $(($RANDOM % 16)) ); done; echo $rndval` + case "$1" in --wait) WAIT=1 @@ -283,9 +289,9 @@ ln -s "/proc/$NSPID/ns/net" "/var/run/netns/$NSPID" # If it's a bridge, we need to create a veth pair [ "$IFTYPE" = bridge ] && { if [ -z "$LOCAL_IFNAME" ]; then - LOCAL_IFNAME="v${CONTAINER_IFNAME}pl${NSPID}" + LOCAL_IFNAME="veth${NSPID}_"; LOCAL_IFNAME=$LOCAL_IFNAME${RAND_STRING:0:$IF_MAX_NAME_SIZE - ${#LOCAL_IFNAME}} fi - GUEST_IFNAME="v${CONTAINER_IFNAME}pg${NSPID}" + GUEST_IFNAME="teth${NSPID}_"; GUEST_IFNAME=$GUEST_IFNAME${RAND_STRING:0:$IF_MAX_NAME_SIZE - ${#GUEST_IFNAME}} # Does the link already exist? if ip link show "$LOCAL_IFNAME" >/dev/null 2>&1; then # link exists, is it in use? @@ -323,7 +329,7 @@ ln -s "/proc/$NSPID/ns/net" "/var/run/netns/$NSPID" if [ ! -z "$DIRECT_PHYS" ]; then GUEST_IFNAME=$IFNAME else - GUEST_IFNAME=ph$NSPID$CONTAINER_IFNAME + GUEST_IFNAME=ph$NSPID; GUEST_IFNAME=$GUEST_IFNAME${RAND_STRING:0:$IF_MAX_NAME_SIZE - ${#GUEST_IFNAME}} ip link add link "$IFNAME" dev "$GUEST_IFNAME" mtu "$MTU" type macvlan mode bridge fi @@ -351,7 +357,7 @@ ln -s "/proc/$NSPID/ns/net" "/var/run/netns/$NSPID" # If its a dummy interface, create a dummy interface. [ "$IFTYPE" = dummy ] && { - GUEST_IFNAME=du$NSPID$CONTAINER_IFNAME + GUEST_IFNAME=du$NSPID; GUEST_IFNAME=$GUEST_IFNAME${RAND_STRING:0:$IF_MAX_NAME_SIZE - ${#GUEST_IFNAME}} ip link add dev "$GUEST_IFNAME" type dummy }