Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ var (
* - When flag=false and empty, uses embedded default_hook.sh as fallback */

/* Run this before getLinuxConfig() in case this is a script
* that's responsible for creating the interface */
* that's responsible for creating the interface.
* Also captures host udev ID_NET_NAME_* properties before driver unbind. */
HookScriptBeforeIfRead = StringEnvVar("CALICOVPP_HOOK_BEFORE_IF_READ", "")
/* Bash script template run just after getting config
from $CALICOVPP_INTERFACE & before starting VPP */
Expand Down Expand Up @@ -312,6 +313,7 @@ type CalicoVppDebugConfigType struct {
ServicesEnabled *bool `json:"servicesEnabled,omitempty"`
GSOEnabled *bool `json:"gsoEnabled,omitempty"`
SpreadTxQueuesOnWorkers *bool `json:"spreadTxQueuesOnWorkers,omitempty"`
EnableUdevNetNameRules *bool `json:"enableUdevNetNameRules,omitempty"`
}

func (cfg *CalicoVppDebugConfigType) String() string {
Expand All @@ -329,6 +331,9 @@ func (cfg *CalicoVppDebugConfigType) Validate() (err error) {
if cfg.SpreadTxQueuesOnWorkers == nil {
cfg.SpreadTxQueuesOnWorkers = &False
}
if cfg.EnableUdevNetNameRules == nil {
cfg.EnableUdevNetNameRules = &True
}
return
}

Expand Down
112 changes: 110 additions & 2 deletions config/default_hook.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

HOOK="$0"
INTERFACE_NAME="$1"
chroot /host /bin/sh <<EOSCRIPT
chroot /host /bin/sh -s "$HOOK" "$INTERFACE_NAME" <<'EOSCRIPT'
HOOK="$1"
INTERFACE_NAME="$2"

fix_dns () {
if systemctl status NetworkManager > /dev/null 2>&1; then
Expand Down Expand Up @@ -83,6 +85,107 @@ remove_tweaked_network_file () {
fi
}

capture_udev_net_name_properties () {
echo "default_hook: Capturing udev net name properties for $INTERFACE_NAME..."

UDEV_INFO=$(udevadm info /sys/class/net/$INTERFACE_NAME 2>/dev/null)
if [ -z "$UDEV_INFO" ]; then
echo "default_hook: Failed to get udevadm info for $INTERFACE_NAME"
return
fi

# Extract ID_NET_NAME_* properties
ID_NET_NAME_ONBOARD=$(echo "$UDEV_INFO" | grep "ID_NET_NAME_ONBOARD=" | sed 's/.*ID_NET_NAME_ONBOARD=//')
ID_NET_NAME_SLOT=$(echo "$UDEV_INFO" | grep "ID_NET_NAME_SLOT=" | sed 's/.*ID_NET_NAME_SLOT=//')
ID_NET_NAME_PATH=$(echo "$UDEV_INFO" | grep "ID_NET_NAME_PATH=" | sed 's/.*ID_NET_NAME_PATH=//')
ID_NET_NAME_MAC=$(echo "$UDEV_INFO" | grep "ID_NET_NAME_MAC=" | sed 's/.*ID_NET_NAME_MAC=//')

# Check if we have any properties to save
if [ -z "$ID_NET_NAME_ONBOARD" ] && [ -z "$ID_NET_NAME_SLOT" ] && [ -z "$ID_NET_NAME_PATH" ] && [ -z "$ID_NET_NAME_MAC" ]; then
echo "default_hook: No udev net name properties found for $INTERFACE_NAME"
return
fi

# Get MAC address
MAC_ADDRESS=$(cat /sys/class/net/$INTERFACE_NAME/address 2>/dev/null)
if [ -z "$MAC_ADDRESS" ]; then
echo "default_hook: Failed to get MAC address for $INTERFACE_NAME"
return
fi

# Save properties to temp file for later use
mkdir -p /var/run/vpp
echo "MAC_ADDRESS=$MAC_ADDRESS" > /var/run/vpp/udev_props_$INTERFACE_NAME
[ -n "$ID_NET_NAME_ONBOARD" ] && echo "ID_NET_NAME_ONBOARD=$ID_NET_NAME_ONBOARD" >> /var/run/vpp/udev_props_$INTERFACE_NAME
[ -n "$ID_NET_NAME_SLOT" ] && echo "ID_NET_NAME_SLOT=$ID_NET_NAME_SLOT" >> /var/run/vpp/udev_props_$INTERFACE_NAME
[ -n "$ID_NET_NAME_PATH" ] && echo "ID_NET_NAME_PATH=$ID_NET_NAME_PATH" >> /var/run/vpp/udev_props_$INTERFACE_NAME
[ -n "$ID_NET_NAME_MAC" ] && echo "ID_NET_NAME_MAC=$ID_NET_NAME_MAC" >> /var/run/vpp/udev_props_$INTERFACE_NAME

echo "default_hook: Captured udev properties for $INTERFACE_NAME (MAC: $MAC_ADDRESS)"
[ -n "$ID_NET_NAME_ONBOARD" ] && echo "default_hook: ID_NET_NAME_ONBOARD=$ID_NET_NAME_ONBOARD"
[ -n "$ID_NET_NAME_SLOT" ] && echo "default_hook: ID_NET_NAME_SLOT=$ID_NET_NAME_SLOT"
[ -n "$ID_NET_NAME_PATH" ] && echo "default_hook: ID_NET_NAME_PATH=$ID_NET_NAME_PATH"
[ -n "$ID_NET_NAME_MAC" ] && echo "default_hook: ID_NET_NAME_MAC=$ID_NET_NAME_MAC"
}

create_udev_net_name_rule () {
PROPS_FILE="/var/run/vpp/udev_props_$INTERFACE_NAME"
if [ ! -f "$PROPS_FILE" ]; then
echo "default_hook: No udev properties captured for $INTERFACE_NAME, skipping rule creation"
return
fi

# Source the properties file
. "$PROPS_FILE"

if [ -z "$MAC_ADDRESS" ]; then
echo "default_hook: No MAC address captured for $INTERFACE_NAME, skipping rule creation"
return
fi

echo "default_hook: Creating udev rule for $INTERFACE_NAME with MAC $MAC_ADDRESS..."

# Build the udev rule
RULE_FILE="/etc/udev/rules.d/99-vpp-restore-id_net_name.rules"
echo "# Re-apply ID_NET_NAME_* properties after Calico VPP creates the host-facing tap/tun netdev." > "$RULE_FILE"
printf 'ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="%s"' "$MAC_ADDRESS" >> "$RULE_FILE"

[ -n "$ID_NET_NAME_ONBOARD" ] && printf ', ENV{ID_NET_NAME_ONBOARD}:="%s"' "$ID_NET_NAME_ONBOARD" >> "$RULE_FILE"
[ -n "$ID_NET_NAME_SLOT" ] && printf ', ENV{ID_NET_NAME_SLOT}:="%s"' "$ID_NET_NAME_SLOT" >> "$RULE_FILE"
[ -n "$ID_NET_NAME_PATH" ] && printf ', ENV{ID_NET_NAME_PATH}:="%s"' "$ID_NET_NAME_PATH" >> "$RULE_FILE"
[ -n "$ID_NET_NAME_MAC" ] && printf ', ENV{ID_NET_NAME_MAC}:="%s"' "$ID_NET_NAME_MAC" >> "$RULE_FILE"

echo "" >> "$RULE_FILE"

echo "default_hook: Created udev rule file at $RULE_FILE"

# Reload udev rules
udevadm control --reload-rules

# Trigger udev for net subsystem to apply the stored ID_NET_NAME_* properties
udevadm trigger --subsystem-match=net --action=add
echo "default_hook: Triggered udev to apply the stored ID_NET_NAME_* properties"
}

remove_udev_net_name_rule () {
RULE_FILE="/etc/udev/rules.d/99-vpp-restore-id_net_name.rules"
PROPS_FILE="/var/run/vpp/udev_props_$INTERFACE_NAME"

if [ -f "$RULE_FILE" ]; then
echo "default_hook: Removing udev rule file $RULE_FILE..."
rm -f "$RULE_FILE"
udevadm control --reload-rules

# Trigger udev for net subsystem to remove the stored ID_NET_NAME_* properties
udevadm trigger --subsystem-match=net --action=change
echo "default_hook: Triggered udev to remove the stored ID_NET_NAME_* properties"
fi

if [ -f "$PROPS_FILE" ]; then
rm -f "$PROPS_FILE"
fi
}

echo "default_hook: Uplink interface name=$INTERFACE_NAME"
if which systemctl > /dev/null; then
echo "default_hook: using systemctl..."
Expand All @@ -91,18 +194,23 @@ else
exit 1
fi

if [ "$HOOK" = "BEFORE_VPP_RUN" ]; then
if [ "$HOOK" = "BEFORE_IF_READ" ]; then
capture_udev_net_name_properties
elif [ "$HOOK" = "BEFORE_VPP_RUN" ]; then
fix_dns
save_network_file
elif [ "$HOOK" = "VPP_RUNNING" ]; then
create_udev_net_name_rule
restart_network
tweak_network_file
elif [ "$HOOK" = "VPP_DONE_OK" ]; then
undo_dns_fix
remove_udev_net_name_rule
remove_tweaked_network_file
restart_network
elif [ "$HOOK" = "VPP_ERRORED" ]; then
undo_dns_fix
remove_udev_net_name_rule
remove_tweaked_network_file
restart_network
fi
Expand Down
Loading
Loading