i10c-beta
changed/i10c-beta/hyperv-daemons-0-0.47.20220731git.el10
commit
d59fac4797
@ -0,0 +1,411 @@
|
||||
From e24f15d5aa258daabb2c34a7b9fed348ac63705d Mon Sep 17 00:00:00 2001
|
||||
From: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
Date: Thu, 6 May 2021 12:53:31 +0200
|
||||
Subject: [PATCH 03/14] Add vmbus_testing tool build files
|
||||
|
||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-MergeRequest: 9: Synchronize RHEL 9 changes to RHEL 10
|
||||
RH-Jira: RHEL-40107 RHEL-40679
|
||||
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||
RH-Commit: [3/14] 384e79f48e6f4665f90fd3b2b17fcaef2178a674 (mrezanin/centos-git-hyperv-daemons)
|
||||
|
||||
Add the vmbus_testing tool to redhat build dirs
|
||||
|
||||
(cherry-pick from rhel 8.4.0 commit d8ca5e0)
|
||||
Signed-off-by: Mohammed Gamal <mgamal@redhat.com>
|
||||
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
|
||||
patch_name: 0005-Add-vmbus_testing-tool-build-files.patch
|
||||
present_in_specfile: true
|
||||
location_in_specfile: 5
|
||||
---
|
||||
.distro/hyperv-daemons.spec | 2 +
|
||||
vmbus_testing | 376 ++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 378 insertions(+)
|
||||
create mode 100755 vmbus_testing
|
||||
|
||||
diff --git a/vmbus_testing b/vmbus_testing
|
||||
new file mode 100755
|
||||
index 0000000..e721290
|
||||
--- /dev/null
|
||||
+++ b/vmbus_testing
|
||||
@@ -0,0 +1,376 @@
|
||||
+#!/usr/bin/env python3
|
||||
+# SPDX-License-Identifier: GPL-2.0
|
||||
+#
|
||||
+# Program to allow users to fuzz test Hyper-V drivers
|
||||
+# by interfacing with Hyper-V debugfs attributes.
|
||||
+# Current test methods available:
|
||||
+# 1. delay testing
|
||||
+#
|
||||
+# Current file/directory structure of hyper-V debugfs:
|
||||
+# /sys/kernel/debug/hyperv/UUID
|
||||
+# /sys/kernel/debug/hyperv/UUID/<test-state filename>
|
||||
+# /sys/kernel/debug/hyperv/UUID/<test-method sub-directory>
|
||||
+#
|
||||
+# author: Branden Bonaby <brandonbonaby94@gmail.com>
|
||||
+
|
||||
+import os
|
||||
+import cmd
|
||||
+import argparse
|
||||
+import glob
|
||||
+from argparse import RawDescriptionHelpFormatter
|
||||
+from argparse import RawTextHelpFormatter
|
||||
+from enum import Enum
|
||||
+
|
||||
+# Do not change unless, you change the debugfs attributes
|
||||
+# in /drivers/hv/debugfs.c. All fuzz testing
|
||||
+# attributes will start with "fuzz_test".
|
||||
+
|
||||
+# debugfs path for hyperv must exist before proceeding
|
||||
+debugfs_hyperv_path = "/sys/kernel/debug/hyperv"
|
||||
+if not os.path.isdir(debugfs_hyperv_path):
|
||||
+ print("{} doesn't exist/check permissions".format(debugfs_hyperv_path))
|
||||
+ exit(-1)
|
||||
+
|
||||
+class dev_state(Enum):
|
||||
+ off = 0
|
||||
+ on = 1
|
||||
+
|
||||
+# File names, that correspond to the files created in
|
||||
+# /drivers/hv/debugfs.c
|
||||
+class f_names(Enum):
|
||||
+ state_f = "fuzz_test_state"
|
||||
+ buff_f = "fuzz_test_buffer_interrupt_delay"
|
||||
+ mess_f = "fuzz_test_message_delay"
|
||||
+
|
||||
+# Both single_actions and all_actions are used
|
||||
+# for error checking and to allow for some subparser
|
||||
+# names to be abbreviated. Do not abbreviate the
|
||||
+# test method names, as it will become less intuitive
|
||||
+# as to what the user can do. If you do decide to
|
||||
+# abbreviate the test method name, make sure the main
|
||||
+# function reflects this change.
|
||||
+
|
||||
+all_actions = [
|
||||
+ "disable_all",
|
||||
+ "D",
|
||||
+ "enable_all",
|
||||
+ "view_all",
|
||||
+ "V"
|
||||
+]
|
||||
+
|
||||
+single_actions = [
|
||||
+ "disable_single",
|
||||
+ "d",
|
||||
+ "enable_single",
|
||||
+ "view_single",
|
||||
+ "v"
|
||||
+]
|
||||
+
|
||||
+def main():
|
||||
+
|
||||
+ file_map = recursive_file_lookup(debugfs_hyperv_path, dict())
|
||||
+ args = parse_args()
|
||||
+ if (not args.action):
|
||||
+ print ("Error, no options selected...exiting")
|
||||
+ exit(-1)
|
||||
+ arg_set = { k for (k,v) in vars(args).items() if v and k != "action" }
|
||||
+ arg_set.add(args.action)
|
||||
+ path = args.path if "path" in arg_set else None
|
||||
+ if (path and path[-1] == "/"):
|
||||
+ path = path[:-1]
|
||||
+ validate_args_path(path, arg_set, file_map)
|
||||
+ if (path and "enable_single" in arg_set):
|
||||
+ state_path = locate_state(path, file_map)
|
||||
+ set_test_state(state_path, dev_state.on.value, args.quiet)
|
||||
+
|
||||
+ # Use subparsers as the key for different actions
|
||||
+ if ("delay" in arg_set):
|
||||
+ validate_delay_values(args.delay_time)
|
||||
+ if (args.enable_all):
|
||||
+ set_delay_all_devices(file_map, args.delay_time,
|
||||
+ args.quiet)
|
||||
+ else:
|
||||
+ set_delay_values(path, file_map, args.delay_time,
|
||||
+ args.quiet)
|
||||
+ elif ("disable_all" in arg_set or "D" in arg_set):
|
||||
+ disable_all_testing(file_map)
|
||||
+ elif ("disable_single" in arg_set or "d" in arg_set):
|
||||
+ disable_testing_single_device(path, file_map)
|
||||
+ elif ("view_all" in arg_set or "V" in arg_set):
|
||||
+ get_all_devices_test_status(file_map)
|
||||
+ elif ("view_single" in arg_set or "v" in arg_set):
|
||||
+ get_device_test_values(path, file_map)
|
||||
+
|
||||
+# Get the state location
|
||||
+def locate_state(device, file_map):
|
||||
+ return file_map[device][f_names.state_f.value]
|
||||
+
|
||||
+# Validate delay values to make sure they are acceptable to
|
||||
+# enable delays on a device
|
||||
+def validate_delay_values(delay):
|
||||
+
|
||||
+ if (delay[0] == -1 and delay[1] == -1):
|
||||
+ print("\nError, At least 1 value must be greater than 0")
|
||||
+ exit(-1)
|
||||
+ for i in delay:
|
||||
+ if (i < -1 or i == 0 or i > 1000):
|
||||
+ print("\nError, Values must be equal to -1 "
|
||||
+ "or be > 0 and <= 1000")
|
||||
+ exit(-1)
|
||||
+
|
||||
+# Validate argument path
|
||||
+def validate_args_path(path, arg_set, file_map):
|
||||
+
|
||||
+ if (not path and any(element in arg_set for element in single_actions)):
|
||||
+ print("Error, path (-p) REQUIRED for the specified option. "
|
||||
+ "Use (-h) to check usage.")
|
||||
+ exit(-1)
|
||||
+ elif (path and any(item in arg_set for item in all_actions)):
|
||||
+ print("Error, path (-p) NOT REQUIRED for the specified option. "
|
||||
+ "Use (-h) to check usage." )
|
||||
+ exit(-1)
|
||||
+ elif (path not in file_map and any(item in arg_set
|
||||
+ for item in single_actions)):
|
||||
+ print("Error, path '{}' not a valid vmbus device".format(path))
|
||||
+ exit(-1)
|
||||
+
|
||||
+# display Testing status of single device
|
||||
+def get_device_test_values(path, file_map):
|
||||
+
|
||||
+ for name in file_map[path]:
|
||||
+ file_location = file_map[path][name]
|
||||
+ print( name + " = " + str(read_test_files(file_location)))
|
||||
+
|
||||
+# Create a map of the vmbus devices and their associated files
|
||||
+# [key=device, value = [key = filename, value = file path]]
|
||||
+def recursive_file_lookup(path, file_map):
|
||||
+
|
||||
+ for f_path in glob.iglob(path + '**/*'):
|
||||
+ if (os.path.isfile(f_path)):
|
||||
+ if (f_path.rsplit("/",2)[0] == debugfs_hyperv_path):
|
||||
+ directory = f_path.rsplit("/",1)[0]
|
||||
+ else:
|
||||
+ directory = f_path.rsplit("/",2)[0]
|
||||
+ f_name = f_path.split("/")[-1]
|
||||
+ if (file_map.get(directory)):
|
||||
+ file_map[directory].update({f_name:f_path})
|
||||
+ else:
|
||||
+ file_map[directory] = {f_name:f_path}
|
||||
+ elif (os.path.isdir(f_path)):
|
||||
+ recursive_file_lookup(f_path,file_map)
|
||||
+ return file_map
|
||||
+
|
||||
+# display Testing state of devices
|
||||
+def get_all_devices_test_status(file_map):
|
||||
+
|
||||
+ for device in file_map:
|
||||
+ if (get_test_state(locate_state(device, file_map)) is 1):
|
||||
+ print("Testing = ON for: {}"
|
||||
+ .format(device.split("/")[5]))
|
||||
+ else:
|
||||
+ print("Testing = OFF for: {}"
|
||||
+ .format(device.split("/")[5]))
|
||||
+
|
||||
+# read the vmbus device files, path must be absolute path before calling
|
||||
+def read_test_files(path):
|
||||
+ try:
|
||||
+ with open(path,"r") as f:
|
||||
+ file_value = f.readline().strip()
|
||||
+ return int(file_value)
|
||||
+
|
||||
+ except IOError as e:
|
||||
+ errno, strerror = e.args
|
||||
+ print("I/O error({0}): {1} on file {2}"
|
||||
+ .format(errno, strerror, path))
|
||||
+ exit(-1)
|
||||
+ except ValueError:
|
||||
+ print ("Element to int conversion error in: \n{}".format(path))
|
||||
+ exit(-1)
|
||||
+
|
||||
+# writing to vmbus device files, path must be absolute path before calling
|
||||
+def write_test_files(path, value):
|
||||
+
|
||||
+ try:
|
||||
+ with open(path,"w") as f:
|
||||
+ f.write("{}".format(value))
|
||||
+ except IOError as e:
|
||||
+ errno, strerror = e.args
|
||||
+ print("I/O error({0}): {1} on file {2}"
|
||||
+ .format(errno, strerror, path))
|
||||
+ exit(-1)
|
||||
+
|
||||
+# set testing state of device
|
||||
+def set_test_state(state_path, state_value, quiet):
|
||||
+
|
||||
+ write_test_files(state_path, state_value)
|
||||
+ if (get_test_state(state_path) is 1):
|
||||
+ if (not quiet):
|
||||
+ print("Testing = ON for device: {}"
|
||||
+ .format(state_path.split("/")[5]))
|
||||
+ else:
|
||||
+ if (not quiet):
|
||||
+ print("Testing = OFF for device: {}"
|
||||
+ .format(state_path.split("/")[5]))
|
||||
+
|
||||
+# get testing state of device
|
||||
+def get_test_state(state_path):
|
||||
+ #state == 1 - test = ON
|
||||
+ #state == 0 - test = OFF
|
||||
+ return read_test_files(state_path)
|
||||
+
|
||||
+# write 1 - 1000 microseconds, into a single device using the
|
||||
+# fuzz_test_buffer_interrupt_delay and fuzz_test_message_delay
|
||||
+# debugfs attributes
|
||||
+def set_delay_values(device, file_map, delay_length, quiet):
|
||||
+
|
||||
+ try:
|
||||
+ interrupt = file_map[device][f_names.buff_f.value]
|
||||
+ message = file_map[device][f_names.mess_f.value]
|
||||
+
|
||||
+ # delay[0]- buffer interrupt delay, delay[1]- message delay
|
||||
+ if (delay_length[0] >= 0 and delay_length[0] <= 1000):
|
||||
+ write_test_files(interrupt, delay_length[0])
|
||||
+ if (delay_length[1] >= 0 and delay_length[1] <= 1000):
|
||||
+ write_test_files(message, delay_length[1])
|
||||
+ if (not quiet):
|
||||
+ print("Buffer delay testing = {} for: {}"
|
||||
+ .format(read_test_files(interrupt),
|
||||
+ interrupt.split("/")[5]))
|
||||
+ print("Message delay testing = {} for: {}"
|
||||
+ .format(read_test_files(message),
|
||||
+ message.split("/")[5]))
|
||||
+ except IOError as e:
|
||||
+ errno, strerror = e.args
|
||||
+ print("I/O error({0}): {1} on files {2}{3}"
|
||||
+ .format(errno, strerror, interrupt, message))
|
||||
+ exit(-1)
|
||||
+
|
||||
+# enabling delay testing on all devices
|
||||
+def set_delay_all_devices(file_map, delay, quiet):
|
||||
+
|
||||
+ for device in (file_map):
|
||||
+ set_test_state(locate_state(device, file_map),
|
||||
+ dev_state.on.value,
|
||||
+ quiet)
|
||||
+ set_delay_values(device, file_map, delay, quiet)
|
||||
+
|
||||
+# disable all testing on a SINGLE device.
|
||||
+def disable_testing_single_device(device, file_map):
|
||||
+
|
||||
+ for name in file_map[device]:
|
||||
+ file_location = file_map[device][name]
|
||||
+ write_test_files(file_location, dev_state.off.value)
|
||||
+ print("ALL testing now OFF for {}".format(device.split("/")[-1]))
|
||||
+
|
||||
+# disable all testing on ALL devices
|
||||
+def disable_all_testing(file_map):
|
||||
+
|
||||
+ for device in file_map:
|
||||
+ disable_testing_single_device(device, file_map)
|
||||
+
|
||||
+def parse_args():
|
||||
+ parser = argparse.ArgumentParser(prog = "vmbus_testing",usage ="\n"
|
||||
+ "%(prog)s [delay] [-h] [-e|-E] -t [-p]\n"
|
||||
+ "%(prog)s [view_all | V] [-h]\n"
|
||||
+ "%(prog)s [disable_all | D] [-h]\n"
|
||||
+ "%(prog)s [disable_single | d] [-h|-p]\n"
|
||||
+ "%(prog)s [view_single | v] [-h|-p]\n"
|
||||
+ "%(prog)s --version\n",
|
||||
+ description = "\nUse lsvmbus to get vmbus device type "
|
||||
+ "information.\n" "\nThe debugfs root path is "
|
||||
+ "/sys/kernel/debug/hyperv",
|
||||
+ formatter_class = RawDescriptionHelpFormatter)
|
||||
+ subparsers = parser.add_subparsers(dest = "action")
|
||||
+ parser.add_argument("--version", action = "version",
|
||||
+ version = '%(prog)s 0.1.0')
|
||||
+ parser.add_argument("-q","--quiet", action = "store_true",
|
||||
+ help = "silence none important test messages."
|
||||
+ " This will only work when enabling testing"
|
||||
+ " on a device.")
|
||||
+ # Use the path parser to hold the --path attribute so it can
|
||||
+ # be shared between subparsers. Also do the same for the state
|
||||
+ # parser, as all testing methods will use --enable_all and
|
||||
+ # enable_single.
|
||||
+ path_parser = argparse.ArgumentParser(add_help=False)
|
||||
+ path_parser.add_argument("-p","--path", metavar = "",
|
||||
+ help = "Debugfs path to a vmbus device. The path "
|
||||
+ "must be the absolute path to the device.")
|
||||
+ state_parser = argparse.ArgumentParser(add_help=False)
|
||||
+ state_group = state_parser.add_mutually_exclusive_group(required = True)
|
||||
+ state_group.add_argument("-E", "--enable_all", action = "store_const",
|
||||
+ const = "enable_all",
|
||||
+ help = "Enable the specified test type "
|
||||
+ "on ALL vmbus devices.")
|
||||
+ state_group.add_argument("-e", "--enable_single",
|
||||
+ action = "store_const",
|
||||
+ const = "enable_single",
|
||||
+ help = "Enable the specified test type on a "
|
||||
+ "SINGLE vmbus device.")
|
||||
+ parser_delay = subparsers.add_parser("delay",
|
||||
+ parents = [state_parser, path_parser],
|
||||
+ help = "Delay the ring buffer interrupt or the "
|
||||
+ "ring buffer message reads in microseconds.",
|
||||
+ prog = "vmbus_testing",
|
||||
+ usage = "%(prog)s [-h]\n"
|
||||
+ "%(prog)s -E -t [value] [value]\n"
|
||||
+ "%(prog)s -e -t [value] [value] -p",
|
||||
+ description = "Delay the ring buffer interrupt for "
|
||||
+ "vmbus devices, or delay the ring buffer message "
|
||||
+ "reads for vmbus devices (both in microseconds). This "
|
||||
+ "is only on the host to guest channel.")
|
||||
+ parser_delay.add_argument("-t", "--delay_time", metavar = "", nargs = 2,
|
||||
+ type = check_range, default =[0,0], required = (True),
|
||||
+ help = "Set [buffer] & [message] delay time. "
|
||||
+ "Value constraints: -1 == value "
|
||||
+ "or 0 < value <= 1000.\n"
|
||||
+ "Use -1 to keep the previous value for that delay "
|
||||
+ "type, or a value > 0 <= 1000 to change the delay "
|
||||
+ "time.")
|
||||
+ parser_dis_all = subparsers.add_parser("disable_all",
|
||||
+ aliases = ['D'], prog = "vmbus_testing",
|
||||
+ usage = "%(prog)s [disable_all | D] -h\n"
|
||||
+ "%(prog)s [disable_all | D]\n",
|
||||
+ help = "Disable ALL testing on ALL vmbus devices.",
|
||||
+ description = "Disable ALL testing on ALL vmbus "
|
||||
+ "devices.")
|
||||
+ parser_dis_single = subparsers.add_parser("disable_single",
|
||||
+ aliases = ['d'],
|
||||
+ parents = [path_parser], prog = "vmbus_testing",
|
||||
+ usage = "%(prog)s [disable_single | d] -h\n"
|
||||
+ "%(prog)s [disable_single | d] -p\n",
|
||||
+ help = "Disable ALL testing on a SINGLE vmbus device.",
|
||||
+ description = "Disable ALL testing on a SINGLE vmbus "
|
||||
+ "device.")
|
||||
+ parser_view_all = subparsers.add_parser("view_all", aliases = ['V'],
|
||||
+ help = "View the test state for ALL vmbus devices.",
|
||||
+ prog = "vmbus_testing",
|
||||
+ usage = "%(prog)s [view_all | V] -h\n"
|
||||
+ "%(prog)s [view_all | V]\n",
|
||||
+ description = "This shows the test state for ALL the "
|
||||
+ "vmbus devices.")
|
||||
+ parser_view_single = subparsers.add_parser("view_single",
|
||||
+ aliases = ['v'],parents = [path_parser],
|
||||
+ help = "View the test values for a SINGLE vmbus "
|
||||
+ "device.",
|
||||
+ description = "This shows the test values for a SINGLE "
|
||||
+ "vmbus device.", prog = "vmbus_testing",
|
||||
+ usage = "%(prog)s [view_single | v] -h\n"
|
||||
+ "%(prog)s [view_single | v] -p")
|
||||
+
|
||||
+ return parser.parse_args()
|
||||
+
|
||||
+# value checking for range checking input in parser
|
||||
+def check_range(arg1):
|
||||
+
|
||||
+ try:
|
||||
+ val = int(arg1)
|
||||
+ except ValueError as err:
|
||||
+ raise argparse.ArgumentTypeError(str(err))
|
||||
+ if val < -1 or val > 1000:
|
||||
+ message = ("\n\nvalue must be -1 or 0 < value <= 1000. "
|
||||
+ "Value program received: {}\n").format(val)
|
||||
+ raise argparse.ArgumentTypeError(message)
|
||||
+ return val
|
||||
+
|
||||
+if __name__ == "__main__":
|
||||
+ main()
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,68 @@
|
||||
From 935df801defcb3f459891e180e66065030d11612 Mon Sep 17 00:00:00 2001
|
||||
From: Ani Sinha <anisinha@redhat.com>
|
||||
Date: Tue, 10 Oct 2023 11:50:30 +0530
|
||||
Subject: [PATCH 13/14] Changes for adding keyfile support in RHEL specific
|
||||
script
|
||||
|
||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-MergeRequest: 9: Synchronize RHEL 9 changes to RHEL 10
|
||||
RH-Jira: RHEL-40107 RHEL-40679
|
||||
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||
RH-Commit: [13/14] 0dec80310c49a5ccbc6b030ba6c575046b21b60f (mrezanin/centos-git-hyperv-daemons)
|
||||
|
||||
Some adjustments to the RHEL specific customization script in order to support
|
||||
Network Manager keyfiles. These changes were tested internally by Red Hat QE.
|
||||
These changes are mostly trivial and are not pushed upstream at this momemnt.
|
||||
|
||||
See also https://issues.redhat.com/browse/RHEL-14505
|
||||
|
||||
Signed-off-by: Ani Sinha <anisinha@redhat.com>
|
||||
|
||||
patch_name: hpvd-Changes-for-adding-keyfile-support-in-RHEL-specific-.patch
|
||||
present_in_specfile: true
|
||||
location_in_specfile: 16
|
||||
---
|
||||
hv_set_ifconfig.sh | 25 ++++++++++++++-----------
|
||||
1 file changed, 14 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/hv_set_ifconfig.sh b/hv_set_ifconfig.sh
|
||||
index 9c2ee30..0bdf2bc 100644
|
||||
--- a/hv_set_ifconfig.sh
|
||||
+++ b/hv_set_ifconfig.sh
|
||||
@@ -74,19 +74,22 @@
|
||||
# call.
|
||||
#
|
||||
|
||||
+# This is RHEL specific bash script that configures NM keyfiles.
|
||||
+# ifcfg files passed as the first argument to this script remains untouched.
|
||||
|
||||
+if [ -z "$2" ]; then
|
||||
+ echo "No input NM keyfile. Exiting!"
|
||||
+ exit 1
|
||||
+fi
|
||||
|
||||
-echo "IPV6INIT=yes" >> $1
|
||||
-echo "PEERDNS=yes" >> $1
|
||||
-echo "ONBOOT=yes" >> $1
|
||||
+sed -i '/\[ipv4\]/a ignore-auto-dns=false' $2
|
||||
+sed -i '/\[connection\]/a autoconnect=true' $2
|
||||
|
||||
-#Unlike older sysconfig scripts, NetworkManager expects GATEWAYx=ipaddr for all values of x.
|
||||
-#So the first gateway is GATEWAY0 instead of GATEWAY. Other values should remain unchanged.
|
||||
-#Workaround this by replacing GATEWAY= with GATEWAY0=.
|
||||
-sed -i "s/GATEWAY=/GATEWAY0=/" $1
|
||||
+filename="${2##*/}"
|
||||
+chmod 600 $2
|
||||
+cp $2 /etc/NetworkManager/system-connections/
|
||||
|
||||
-cp $1 /etc/sysconfig/network-scripts/
|
||||
+nmcli connection load "/etc/NetworkManager/system-connections/${filename}"
|
||||
+nmcli connection up filename "/etc/NetworkManager/system-connections/${filename}"
|
||||
|
||||
-filename="${1##*/}"
|
||||
-nmcli connection load "/etc/sysconfig/network-scripts/${filename}"
|
||||
-nmcli connection up filename "/etc/sysconfig/network-scripts/${filename}"
|
||||
+exit 0
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,33 @@
|
||||
From 45c529405a747e7be7cc229913393fa34f5cd4ff Mon Sep 17 00:00:00 2001
|
||||
From: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
Date: Thu, 14 Nov 2019 09:45:44 +0100
|
||||
Subject: [PATCH 02/14] Do not set NM_CONTROLLED=no
|
||||
|
||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-MergeRequest: 9: Synchronize RHEL 9 changes to RHEL 10
|
||||
RH-Jira: RHEL-40107 RHEL-40679
|
||||
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||
RH-Commit: [2/14] 3873d86dfc8a13e160b82cbdf3e9aaa52eedb37f (mrezanin/centos-git-hyperv-daemons)
|
||||
|
||||
patch_name: 0002-Do-not-set-NM_CONTROLLED-no.patch
|
||||
present_in_specfile: true
|
||||
location_in_specfile: 2
|
||||
---
|
||||
hv_set_ifconfig.sh | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/hv_set_ifconfig.sh b/hv_set_ifconfig.sh
|
||||
index d10fe35..3dd064c 100644
|
||||
--- a/hv_set_ifconfig.sh
|
||||
+++ b/hv_set_ifconfig.sh
|
||||
@@ -51,7 +51,6 @@
|
||||
|
||||
|
||||
echo "IPV6INIT=yes" >> $1
|
||||
-echo "NM_CONTROLLED=no" >> $1
|
||||
echo "PEERDNS=yes" >> $1
|
||||
echo "ONBOOT=yes" >> $1
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,34 @@
|
||||
From 71c04766e4b8a4edfa8c645d30cea48f825cc1e9 Mon Sep 17 00:00:00 2001
|
||||
From: Till Maas <timaas@redhat.com>
|
||||
Date: Tue, 14 Dec 2021 08:07:40 +0000
|
||||
Subject: [PATCH 05/14] Use filename for connection profile
|
||||
|
||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-MergeRequest: 9: Synchronize RHEL 9 changes to RHEL 10
|
||||
RH-Jira: RHEL-40107 RHEL-40679
|
||||
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||
RH-Commit: [5/14] e91a7aeb17973de8526f325b44cda5af733c43ee (mrezanin/centos-git-hyperv-daemons)
|
||||
|
||||
patch_name: hpvd-Use-filename-for-connection-profile.patch
|
||||
present_in_specfile: true
|
||||
location_in_specfile: 8
|
||||
---
|
||||
hv_set_ifconfig.sh | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hv_set_ifconfig.sh b/hv_set_ifconfig.sh
|
||||
index 5a64efe..146829b 100644
|
||||
--- a/hv_set_ifconfig.sh
|
||||
+++ b/hv_set_ifconfig.sh
|
||||
@@ -57,5 +57,6 @@ echo "ONBOOT=yes" >> $1
|
||||
|
||||
cp $1 /etc/sysconfig/network-scripts/
|
||||
|
||||
-nmcli connection load "/etc/sysconfig/network-scripts/$1"
|
||||
-nmcli connection up filename "/etc/sysconfig/network-scripts/$1"
|
||||
+filename="${1##*/}"
|
||||
+nmcli connection load "/etc/sysconfig/network-scripts/${filename}"
|
||||
+nmcli connection up filename "/etc/sysconfig/network-scripts/${filename}"
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,338 @@
|
||||
From cc43c1ad250ed39ee7d5f5459049b29f1c4a6f42 Mon Sep 17 00:00:00 2001
|
||||
From: Shradha Gupta <shradhagupta@linux.microsoft.com>
|
||||
Date: Fri, 22 Mar 2024 06:46:02 -0700
|
||||
Subject: [PATCH 12/14] hv/hv_kvp_daemon: Handle IPv4 and Ipv6 combination for
|
||||
keyfile format
|
||||
|
||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-MergeRequest: 9: Synchronize RHEL 9 changes to RHEL 10
|
||||
RH-Jira: RHEL-40107 RHEL-40679
|
||||
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||
RH-Commit: [12/14] 936263af9ba1441d37661bfa356c45db782df926 (mrezanin/centos-git-hyperv-daemons)
|
||||
|
||||
If the network configuration strings are passed as a combination of IPv4
|
||||
and IPv6 addresses, the current KVP daemon does not handle processing for
|
||||
the keyfile configuration format.
|
||||
With these changes, the keyfile config generation logic scans through the
|
||||
list twice to generate IPv4 and IPv6 sections for the configuration files
|
||||
to handle this support.
|
||||
|
||||
Testcases ran:Rhel 9, Hyper-V VMs
|
||||
(IPv4 only, IPv6 only, IPv4 and IPv6 combination)
|
||||
|
||||
Cherry-picked from Linux kernel upstream commit
|
||||
f971f6dd3742d2 ("hv/hv_kvp_daemon: Handle IPv4 and Ipv6 combination for keyfile format")
|
||||
Co-developed-by: Ani Sinha <anisinha@redhat.com>
|
||||
Signed-off-by: Ani Sinha <anisinha@redhat.com>
|
||||
Signed-off-by: Shradha Gupta <shradhagupta@linux.microsoft.com>
|
||||
Reviewed-by: Easwar Hariharan <eahariha@linux.microsoft.com>
|
||||
Tested-by: Ani Sinha <anisinha@redhat.com>
|
||||
Reviewed-by: Ani Sinha <anisinha@redhat.com>
|
||||
Link: https://lore.kernel.org/r/1711115162-11629-1-git-send-email-shradhagupta@linux.microsoft.com
|
||||
Signed-off-by: Wei Liu <wei.liu@kernel.org>
|
||||
Message-ID: <1711115162-11629-1-git-send-email-shradhagupta@linux.microsoft.com>
|
||||
|
||||
patch_name: hpvd-hv-hv_kvp_daemon-Handle-IPv4-and-Ipv6-combination-fo.patch
|
||||
present_in_specfile: true
|
||||
location_in_specfile: 15
|
||||
---
|
||||
hv_kvp_daemon.c | 213 ++++++++++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 172 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/hv_kvp_daemon.c b/hv_kvp_daemon.c
|
||||
index 318e2da..ae57bf6 100644
|
||||
--- a/hv_kvp_daemon.c
|
||||
+++ b/hv_kvp_daemon.c
|
||||
@@ -76,6 +76,12 @@ enum {
|
||||
DNS
|
||||
};
|
||||
|
||||
+enum {
|
||||
+ IPV4 = 1,
|
||||
+ IPV6,
|
||||
+ IP_TYPE_MAX
|
||||
+};
|
||||
+
|
||||
static int in_hand_shake;
|
||||
|
||||
static char *os_name = "";
|
||||
@@ -102,6 +108,11 @@ static struct utsname uts_buf;
|
||||
|
||||
#define MAX_FILE_NAME 100
|
||||
#define ENTRIES_PER_BLOCK 50
|
||||
+/*
|
||||
+ * Change this entry if the number of addresses increases in future
|
||||
+ */
|
||||
+#define MAX_IP_ENTRIES 64
|
||||
+#define OUTSTR_BUF_SIZE ((INET6_ADDRSTRLEN + 1) * MAX_IP_ENTRIES)
|
||||
|
||||
struct kvp_record {
|
||||
char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
||||
@@ -1171,6 +1182,18 @@ static int process_ip_string(FILE *f, char *ip_string, int type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int ip_version_check(const char *input_addr)
|
||||
+{
|
||||
+ struct in6_addr addr;
|
||||
+
|
||||
+ if (inet_pton(AF_INET, input_addr, &addr))
|
||||
+ return IPV4;
|
||||
+ else if (inet_pton(AF_INET6, input_addr, &addr))
|
||||
+ return IPV6;
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Only IPv4 subnet strings needs to be converted to plen
|
||||
* For IPv6 the subnet is already privided in plen format
|
||||
@@ -1197,14 +1220,75 @@ static int kvp_subnet_to_plen(char *subnet_addr_str)
|
||||
return plen;
|
||||
}
|
||||
|
||||
+static int process_dns_gateway_nm(FILE *f, char *ip_string, int type,
|
||||
+ int ip_sec)
|
||||
+{
|
||||
+ char addr[INET6_ADDRSTRLEN], *output_str;
|
||||
+ int ip_offset = 0, error = 0, ip_ver;
|
||||
+ char *param_name;
|
||||
+
|
||||
+ if (type == DNS)
|
||||
+ param_name = "dns";
|
||||
+ else if (type == GATEWAY)
|
||||
+ param_name = "gateway";
|
||||
+ else
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ output_str = (char *)calloc(OUTSTR_BUF_SIZE, sizeof(char));
|
||||
+ if (!output_str)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ while (1) {
|
||||
+ memset(addr, 0, sizeof(addr));
|
||||
+
|
||||
+ if (!parse_ip_val_buffer(ip_string, &ip_offset, addr,
|
||||
+ (MAX_IP_ADDR_SIZE * 2)))
|
||||
+ break;
|
||||
+
|
||||
+ ip_ver = ip_version_check(addr);
|
||||
+ if (ip_ver < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if ((ip_ver == IPV4 && ip_sec == IPV4) ||
|
||||
+ (ip_ver == IPV6 && ip_sec == IPV6)) {
|
||||
+ /*
|
||||
+ * do a bound check to avoid out-of bound writes
|
||||
+ */
|
||||
+ if ((OUTSTR_BUF_SIZE - strlen(output_str)) >
|
||||
+ (strlen(addr) + 1)) {
|
||||
+ strncat(output_str, addr,
|
||||
+ OUTSTR_BUF_SIZE -
|
||||
+ strlen(output_str) - 1);
|
||||
+ strncat(output_str, ",",
|
||||
+ OUTSTR_BUF_SIZE -
|
||||
+ strlen(output_str) - 1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (strlen(output_str)) {
|
||||
+ /*
|
||||
+ * This is to get rid of that extra comma character
|
||||
+ * in the end of the string
|
||||
+ */
|
||||
+ output_str[strlen(output_str) - 1] = '\0';
|
||||
+ error = fprintf(f, "%s=%s\n", param_name, output_str);
|
||||
+ }
|
||||
+
|
||||
+ free(output_str);
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet,
|
||||
- int is_ipv6)
|
||||
+ int ip_sec)
|
||||
{
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
char subnet_addr[INET6_ADDRSTRLEN];
|
||||
- int error, i = 0;
|
||||
+ int error = 0, i = 0;
|
||||
int ip_offset = 0, subnet_offset = 0;
|
||||
- int plen;
|
||||
+ int plen, ip_ver;
|
||||
|
||||
memset(addr, 0, sizeof(addr));
|
||||
memset(subnet_addr, 0, sizeof(subnet_addr));
|
||||
@@ -1216,10 +1300,16 @@ static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet,
|
||||
subnet_addr,
|
||||
(MAX_IP_ADDR_SIZE *
|
||||
2))) {
|
||||
- if (!is_ipv6)
|
||||
+ ip_ver = ip_version_check(addr);
|
||||
+ if (ip_ver < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (ip_ver == IPV4 && ip_sec == IPV4)
|
||||
plen = kvp_subnet_to_plen((char *)subnet_addr);
|
||||
- else
|
||||
+ else if (ip_ver == IPV6 && ip_sec == IPV6)
|
||||
plen = atoi(subnet_addr);
|
||||
+ else
|
||||
+ continue;
|
||||
|
||||
if (plen < 0)
|
||||
return plen;
|
||||
@@ -1233,17 +1323,16 @@ static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet,
|
||||
memset(subnet_addr, 0, sizeof(subnet_addr));
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return error;
|
||||
}
|
||||
|
||||
static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
{
|
||||
- int error = 0;
|
||||
+ int error = 0, ip_ver;
|
||||
char if_filename[PATH_MAX];
|
||||
char nm_filename[PATH_MAX];
|
||||
FILE *ifcfg_file, *nmfile;
|
||||
char cmd[PATH_MAX];
|
||||
- int is_ipv6 = 0;
|
||||
char *mac_addr;
|
||||
int str_len;
|
||||
|
||||
@@ -1421,52 +1510,94 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
- if (new_val->addr_family & ADDR_FAMILY_IPV6) {
|
||||
- error = fprintf(nmfile, "\n[ipv6]\n");
|
||||
- if (error < 0)
|
||||
- goto setval_error;
|
||||
- is_ipv6 = 1;
|
||||
- } else {
|
||||
- error = fprintf(nmfile, "\n[ipv4]\n");
|
||||
- if (error < 0)
|
||||
- goto setval_error;
|
||||
- }
|
||||
-
|
||||
/*
|
||||
* Now we populate the keyfile format
|
||||
+ *
|
||||
+ * The keyfile format expects the IPv6 and IPv4 configuration in
|
||||
+ * different sections. Therefore we iterate through the list twice,
|
||||
+ * once to populate the IPv4 section and the next time for IPv6
|
||||
*/
|
||||
+ ip_ver = IPV4;
|
||||
+ do {
|
||||
+ if (ip_ver == IPV4) {
|
||||
+ error = fprintf(nmfile, "\n[ipv4]\n");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ } else {
|
||||
+ error = fprintf(nmfile, "\n[ipv6]\n");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
|
||||
- if (new_val->dhcp_enabled) {
|
||||
- error = kvp_write_file(nmfile, "method", "", "auto");
|
||||
- if (error < 0)
|
||||
- goto setval_error;
|
||||
- } else {
|
||||
- error = kvp_write_file(nmfile, "method", "", "manual");
|
||||
+ /*
|
||||
+ * Write the configuration for ipaddress, netmask, gateway and
|
||||
+ * name services
|
||||
+ */
|
||||
+ error = process_ip_string_nm(nmfile, (char *)new_val->ip_addr,
|
||||
+ (char *)new_val->sub_net,
|
||||
+ ip_ver);
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
- }
|
||||
|
||||
- /*
|
||||
- * Write the configuration for ipaddress, netmask, gateway and
|
||||
- * name services
|
||||
- */
|
||||
- error = process_ip_string_nm(nmfile, (char *)new_val->ip_addr,
|
||||
- (char *)new_val->sub_net, is_ipv6);
|
||||
- if (error < 0)
|
||||
- goto setval_error;
|
||||
+ /*
|
||||
+ * As dhcp_enabled is only valid for ipv4, we do not set dhcp
|
||||
+ * methods for ipv6 based on dhcp_enabled flag.
|
||||
+ *
|
||||
+ * For ipv4, set method to manual only when dhcp_enabled is
|
||||
+ * false and specific ipv4 addresses are configured. If neither
|
||||
+ * dhcp_enabled is true and no ipv4 addresses are configured,
|
||||
+ * set method to 'disabled'.
|
||||
+ *
|
||||
+ * For ipv6, set method to manual when we configure ipv6
|
||||
+ * addresses. Otherwise set method to 'auto' so that SLAAC from
|
||||
+ * RA may be used.
|
||||
+ */
|
||||
+ if (ip_ver == IPV4) {
|
||||
+ if (new_val->dhcp_enabled) {
|
||||
+ error = kvp_write_file(nmfile, "method", "",
|
||||
+ "auto");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ } else if (error) {
|
||||
+ error = kvp_write_file(nmfile, "method", "",
|
||||
+ "manual");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ } else {
|
||||
+ error = kvp_write_file(nmfile, "method", "",
|
||||
+ "disabled");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
+ } else if (ip_ver == IPV6) {
|
||||
+ if (error) {
|
||||
+ error = kvp_write_file(nmfile, "method", "",
|
||||
+ "manual");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ } else {
|
||||
+ error = kvp_write_file(nmfile, "method", "",
|
||||
+ "auto");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- /* we do not want ipv4 addresses in ipv6 section and vice versa */
|
||||
- if (is_ipv6 != is_ipv4((char *)new_val->gate_way)) {
|
||||
- error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
|
||||
+ error = process_dns_gateway_nm(nmfile,
|
||||
+ (char *)new_val->gate_way,
|
||||
+ GATEWAY, ip_ver);
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
- }
|
||||
|
||||
- if (is_ipv6 != is_ipv4((char *)new_val->dns_addr)) {
|
||||
- error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
|
||||
+ error = process_dns_gateway_nm(nmfile,
|
||||
+ (char *)new_val->dns_addr, DNS,
|
||||
+ ip_ver);
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
- }
|
||||
+
|
||||
+ ip_ver++;
|
||||
+ } while (ip_ver < IP_TYPE_MAX);
|
||||
+
|
||||
fclose(nmfile);
|
||||
fclose(ifcfg_file);
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,103 @@
|
||||
From a8335c9675d22f8ed51a98e2f6b0f6f684d07793 Mon Sep 17 00:00:00 2001
|
||||
From: Ani Sinha <anisinha@redhat.com>
|
||||
Date: Mon, 16 Oct 2023 19:03:33 +0530
|
||||
Subject: [PATCH 11/14] hv/hv_kvp_daemon: Some small fixes for handling NM
|
||||
keyfiles
|
||||
|
||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-MergeRequest: 9: Synchronize RHEL 9 changes to RHEL 10
|
||||
RH-Jira: RHEL-40107 RHEL-40679
|
||||
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||
RH-Commit: [11/14] 55156e8fdd215ce1308887ea463a17ba614b1837 (mrezanin/centos-git-hyperv-daemons)
|
||||
|
||||
Some small fixes:
|
||||
- lets make sure we are not adding ipv4 addresses in ipv6 section in
|
||||
keyfile and vice versa.
|
||||
- ADDR_FAMILY_IPV6 is a bit in addr_family. Test that bit instead of
|
||||
checking the whole value of addr_family.
|
||||
- Some trivial fixes in hv_set_ifconfig.sh.
|
||||
|
||||
These fixes are proposed after doing some internal testing at Red Hat.
|
||||
|
||||
Cherry-picked from upstream linux
|
||||
kernel commit c3803203bc5ec910a ("hv/hv_kvp_daemon: Some small fixes for handling NM keyfiles")
|
||||
CC: Shradha Gupta <shradhagupta@linux.microsoft.com>
|
||||
CC: Saurabh Sengar <ssengar@linux.microsoft.com>
|
||||
Fixes: 42999c904612 ("hv/hv_kvp_daemon:Support for keyfile based connection profile")
|
||||
Signed-off-by: Ani Sinha <anisinha@redhat.com>
|
||||
Reviewed-by: Shradha Gupta <Shradhagupta@linux.microsoft.com>
|
||||
Signed-off-by: Wei Liu <wei.liu@kernel.org>
|
||||
Message-ID: <20231016133122.2419537-1-anisinha@redhat.com>
|
||||
|
||||
patch_name: hpvd-hv-hv_kvp_daemon-Some-small-fixes-for-handling-NM-ke.patch
|
||||
present_in_specfile: true
|
||||
location_in_specfile: 14
|
||||
---
|
||||
hv_kvp_daemon.c | 20 ++++++++++++--------
|
||||
hv_set_ifconfig.sh | 4 ++--
|
||||
2 files changed, 14 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/hv_kvp_daemon.c b/hv_kvp_daemon.c
|
||||
index 264eeb9..318e2da 100644
|
||||
--- a/hv_kvp_daemon.c
|
||||
+++ b/hv_kvp_daemon.c
|
||||
@@ -1421,7 +1421,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
- if (new_val->addr_family == ADDR_FAMILY_IPV6) {
|
||||
+ if (new_val->addr_family & ADDR_FAMILY_IPV6) {
|
||||
error = fprintf(nmfile, "\n[ipv6]\n");
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
@@ -1455,14 +1455,18 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
|
||||
- error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
|
||||
- if (error < 0)
|
||||
- goto setval_error;
|
||||
-
|
||||
- error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
|
||||
- if (error < 0)
|
||||
- goto setval_error;
|
||||
+ /* we do not want ipv4 addresses in ipv6 section and vice versa */
|
||||
+ if (is_ipv6 != is_ipv4((char *)new_val->gate_way)) {
|
||||
+ error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
|
||||
+ if (is_ipv6 != is_ipv4((char *)new_val->dns_addr)) {
|
||||
+ error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
fclose(nmfile);
|
||||
fclose(ifcfg_file);
|
||||
|
||||
diff --git a/hv_set_ifconfig.sh b/hv_set_ifconfig.sh
|
||||
index 35aae6f..9c2ee30 100644
|
||||
--- a/hv_set_ifconfig.sh
|
||||
+++ b/hv_set_ifconfig.sh
|
||||
@@ -53,7 +53,7 @@
|
||||
# or "manual" if no boot-time protocol should be used)
|
||||
#
|
||||
# address1=ipaddr1/plen
|
||||
-# address=ipaddr2/plen
|
||||
+# address2=ipaddr2/plen
|
||||
#
|
||||
# gateway=gateway1;gateway2
|
||||
#
|
||||
@@ -61,7 +61,7 @@
|
||||
#
|
||||
# [ipv6]
|
||||
# address1=ipaddr1/plen
|
||||
-# address2=ipaddr1/plen
|
||||
+# address2=ipaddr2/plen
|
||||
#
|
||||
# gateway=gateway1;gateway2
|
||||
#
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,429 @@
|
||||
From cdf838e027ed7b6438dc86df6329bf46a7541b4f Mon Sep 17 00:00:00 2001
|
||||
From: Shradha Gupta <shradhagupta@linux.microsoft.com>
|
||||
Date: Mon, 9 Oct 2023 03:38:40 -0700
|
||||
Subject: [PATCH 10/14] hv/hv_kvp_daemon:Support for keyfile based connection
|
||||
profile
|
||||
|
||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-MergeRequest: 9: Synchronize RHEL 9 changes to RHEL 10
|
||||
RH-Jira: RHEL-40107 RHEL-40679
|
||||
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||
RH-Commit: [10/14] 16745685ef5d6c90f95acdd665a348ce8f30a684 (mrezanin/centos-git-hyperv-daemons)
|
||||
|
||||
Ifcfg config file support in NetworkManger is deprecated. This patch
|
||||
provides support for the new keyfile config format for connection
|
||||
profiles in NetworkManager. The patch modifies the hv_kvp_daemon code
|
||||
to generate the new network configuration in keyfile
|
||||
format(.ini-style format) along with a ifcfg format configuration.
|
||||
The ifcfg format configuration is also retained to support easy
|
||||
backward compatibility for distro vendors. These configurations are
|
||||
stored in temp files which are further translated using the
|
||||
hv_set_ifconfig.sh script. This script is implemented by individual
|
||||
distros based on the network management commands supported.
|
||||
For example, RHEL's implementation could be found here:
|
||||
https://gitlab.com/redhat/centos-stream/src/hyperv-daemons/-/blob/c9s/hv_set_ifconfig.sh
|
||||
Debian's implementation could be found here:
|
||||
https://github.com/endlessm/linux/blob/master/debian/cloud-tools/hv_set_ifconfig
|
||||
|
||||
The next part of this support is to let the Distro vendors consume
|
||||
these modified implementations to the new configuration format.
|
||||
|
||||
Cherry-picked from upstream linux
|
||||
kernel commit 42999c904612 ("hv/hv_kvp_daemon:Support for keyfile based connection profile")
|
||||
Tested-on: Rhel9(Hyper-V, Azure)(nm and ifcfg files verified)
|
||||
Signed-off-by: Shradha Gupta <shradhagupta@linux.microsoft.com>
|
||||
Reviewed-by: Saurabh Sengar <ssengar@linux.microsoft.com>
|
||||
Reviewed-by: Ani Sinha <anisinha@redhat.com>
|
||||
Signed-off-by: Wei Liu <wei.liu@kernel.org>
|
||||
Link: https://lore.kernel.org/r/1696847920-31125-1-git-send-email-shradhagupta@linux.microsoft.com
|
||||
|
||||
patch_name: hpvd-hv-hv_kvp_daemon-Support-for-keyfile-based-connectio.patch
|
||||
present_in_specfile: true
|
||||
location_in_specfile: 13
|
||||
---
|
||||
hv_kvp_daemon.c | 233 +++++++++++++++++++++++++++++++++++++++------
|
||||
hv_set_ifconfig.sh | 30 +++++-
|
||||
2 files changed, 230 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/hv_kvp_daemon.c b/hv_kvp_daemon.c
|
||||
index 27f5e7d..264eeb9 100644
|
||||
--- a/hv_kvp_daemon.c
|
||||
+++ b/hv_kvp_daemon.c
|
||||
@@ -1171,12 +1171,79 @@ static int process_ip_string(FILE *f, char *ip_string, int type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Only IPv4 subnet strings needs to be converted to plen
|
||||
+ * For IPv6 the subnet is already privided in plen format
|
||||
+ */
|
||||
+static int kvp_subnet_to_plen(char *subnet_addr_str)
|
||||
+{
|
||||
+ int plen = 0;
|
||||
+ struct in_addr subnet_addr4;
|
||||
+
|
||||
+ /*
|
||||
+ * Convert subnet address to binary representation
|
||||
+ */
|
||||
+ if (inet_pton(AF_INET, subnet_addr_str, &subnet_addr4) == 1) {
|
||||
+ uint32_t subnet_mask = ntohl(subnet_addr4.s_addr);
|
||||
+
|
||||
+ while (subnet_mask & 0x80000000) {
|
||||
+ plen++;
|
||||
+ subnet_mask <<= 1;
|
||||
+ }
|
||||
+ } else {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return plen;
|
||||
+}
|
||||
+
|
||||
+static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet,
|
||||
+ int is_ipv6)
|
||||
+{
|
||||
+ char addr[INET6_ADDRSTRLEN];
|
||||
+ char subnet_addr[INET6_ADDRSTRLEN];
|
||||
+ int error, i = 0;
|
||||
+ int ip_offset = 0, subnet_offset = 0;
|
||||
+ int plen;
|
||||
+
|
||||
+ memset(addr, 0, sizeof(addr));
|
||||
+ memset(subnet_addr, 0, sizeof(subnet_addr));
|
||||
+
|
||||
+ while (parse_ip_val_buffer(ip_string, &ip_offset, addr,
|
||||
+ (MAX_IP_ADDR_SIZE * 2)) &&
|
||||
+ parse_ip_val_buffer(subnet,
|
||||
+ &subnet_offset,
|
||||
+ subnet_addr,
|
||||
+ (MAX_IP_ADDR_SIZE *
|
||||
+ 2))) {
|
||||
+ if (!is_ipv6)
|
||||
+ plen = kvp_subnet_to_plen((char *)subnet_addr);
|
||||
+ else
|
||||
+ plen = atoi(subnet_addr);
|
||||
+
|
||||
+ if (plen < 0)
|
||||
+ return plen;
|
||||
+
|
||||
+ error = fprintf(f, "address%d=%s/%d\n", ++i, (char *)addr,
|
||||
+ plen);
|
||||
+ if (error < 0)
|
||||
+ return error;
|
||||
+
|
||||
+ memset(addr, 0, sizeof(addr));
|
||||
+ memset(subnet_addr, 0, sizeof(subnet_addr));
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
{
|
||||
int error = 0;
|
||||
- char if_file[PATH_MAX];
|
||||
- FILE *file;
|
||||
+ char if_filename[PATH_MAX];
|
||||
+ char nm_filename[PATH_MAX];
|
||||
+ FILE *ifcfg_file, *nmfile;
|
||||
char cmd[PATH_MAX];
|
||||
+ int is_ipv6 = 0;
|
||||
char *mac_addr;
|
||||
int str_len;
|
||||
|
||||
@@ -1197,7 +1264,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
* in a given distro to configure the interface and so are free
|
||||
* ignore information that may not be relevant.
|
||||
*
|
||||
- * Here is the format of the ip configuration file:
|
||||
+ * Here is the ifcfg format of the ip configuration file:
|
||||
*
|
||||
* HWADDR=macaddr
|
||||
* DEVICE=interface name
|
||||
@@ -1220,6 +1287,32 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
* tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as
|
||||
* IPV6NETMASK.
|
||||
*
|
||||
+ * Here is the keyfile format of the ip configuration file:
|
||||
+ *
|
||||
+ * [ethernet]
|
||||
+ * mac-address=macaddr
|
||||
+ * [connection]
|
||||
+ * interface-name=interface name
|
||||
+ *
|
||||
+ * [ipv4]
|
||||
+ * method=<protocol> (where <protocol> is "auto" if DHCP is configured
|
||||
+ * or "manual" if no boot-time protocol should be used)
|
||||
+ *
|
||||
+ * address1=ipaddr1/plen
|
||||
+ * address2=ipaddr2/plen
|
||||
+ *
|
||||
+ * gateway=gateway1;gateway2
|
||||
+ *
|
||||
+ * dns=dns1;dns2
|
||||
+ *
|
||||
+ * [ipv6]
|
||||
+ * address1=ipaddr1/plen
|
||||
+ * address2=ipaddr2/plen
|
||||
+ *
|
||||
+ * gateway=gateway1;gateway2
|
||||
+ *
|
||||
+ * dns=dns1;dns2
|
||||
+ *
|
||||
* The host can specify multiple ipv4 and ipv6 addresses to be
|
||||
* configured for the interface. Furthermore, the configuration
|
||||
* needs to be persistent. A subsequent GET call on the interface
|
||||
@@ -1227,14 +1320,29 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
* call.
|
||||
*/
|
||||
|
||||
- snprintf(if_file, sizeof(if_file), "%s%s%s", KVP_CONFIG_LOC,
|
||||
- "/ifcfg-", if_name);
|
||||
+ /*
|
||||
+ * We are populating both ifcfg and nmconnection files
|
||||
+ */
|
||||
+ snprintf(if_filename, sizeof(if_filename), "%s%s%s", KVP_CONFIG_LOC,
|
||||
+ "/ifcfg-", if_name);
|
||||
|
||||
- file = fopen(if_file, "w");
|
||||
+ ifcfg_file = fopen(if_filename, "w");
|
||||
|
||||
- if (file == NULL) {
|
||||
+ if (!ifcfg_file) {
|
||||
syslog(LOG_ERR, "Failed to open config file; error: %d %s",
|
||||
- errno, strerror(errno));
|
||||
+ errno, strerror(errno));
|
||||
+ return HV_E_FAIL;
|
||||
+ }
|
||||
+
|
||||
+ snprintf(nm_filename, sizeof(nm_filename), "%s%s%s%s", KVP_CONFIG_LOC,
|
||||
+ "/", if_name, ".nmconnection");
|
||||
+
|
||||
+ nmfile = fopen(nm_filename, "w");
|
||||
+
|
||||
+ if (!nmfile) {
|
||||
+ syslog(LOG_ERR, "Failed to open config file; error: %d %s",
|
||||
+ errno, strerror(errno));
|
||||
+ fclose(ifcfg_file);
|
||||
return HV_E_FAIL;
|
||||
}
|
||||
|
||||
@@ -1248,14 +1356,31 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
goto setval_error;
|
||||
}
|
||||
|
||||
- error = kvp_write_file(file, "HWADDR", "", mac_addr);
|
||||
- free(mac_addr);
|
||||
+ error = kvp_write_file(ifcfg_file, "HWADDR", "", mac_addr);
|
||||
+ if (error < 0)
|
||||
+ goto setmac_error;
|
||||
+
|
||||
+ error = kvp_write_file(ifcfg_file, "DEVICE", "", if_name);
|
||||
+ if (error < 0)
|
||||
+ goto setmac_error;
|
||||
+
|
||||
+ error = fprintf(nmfile, "\n[connection]\n");
|
||||
+ if (error < 0)
|
||||
+ goto setmac_error;
|
||||
+
|
||||
+ error = kvp_write_file(nmfile, "interface-name", "", if_name);
|
||||
if (error)
|
||||
- goto setval_error;
|
||||
+ goto setmac_error;
|
||||
|
||||
- error = kvp_write_file(file, "DEVICE", "", if_name);
|
||||
+ error = fprintf(nmfile, "\n[ethernet]\n");
|
||||
+ if (error < 0)
|
||||
+ goto setmac_error;
|
||||
+
|
||||
+ error = kvp_write_file(nmfile, "mac-address", "", mac_addr);
|
||||
if (error)
|
||||
- goto setval_error;
|
||||
+ goto setmac_error;
|
||||
+
|
||||
+ free(mac_addr);
|
||||
|
||||
/*
|
||||
* The dhcp_enabled flag is only for IPv4. In the case the host only
|
||||
@@ -1263,47 +1388,91 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
* proceed to parse and pass the IPv6 information to the
|
||||
* disto-specific script hv_set_ifconfig.
|
||||
*/
|
||||
+
|
||||
+ /*
|
||||
+ * First populate the ifcfg file format
|
||||
+ */
|
||||
if (new_val->dhcp_enabled) {
|
||||
- error = kvp_write_file(file, "BOOTPROTO", "", "dhcp");
|
||||
+ error = kvp_write_file(ifcfg_file, "BOOTPROTO", "", "dhcp");
|
||||
if (error)
|
||||
goto setval_error;
|
||||
-
|
||||
} else {
|
||||
- error = kvp_write_file(file, "BOOTPROTO", "", "none");
|
||||
+ error = kvp_write_file(ifcfg_file, "BOOTPROTO", "", "none");
|
||||
if (error)
|
||||
goto setval_error;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Write the configuration for ipaddress, netmask, gateway and
|
||||
- * name servers.
|
||||
- */
|
||||
-
|
||||
- error = process_ip_string(file, (char *)new_val->ip_addr, IPADDR);
|
||||
+ error = process_ip_string(ifcfg_file, (char *)new_val->ip_addr,
|
||||
+ IPADDR);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
- error = process_ip_string(file, (char *)new_val->sub_net, NETMASK);
|
||||
+ error = process_ip_string(ifcfg_file, (char *)new_val->sub_net,
|
||||
+ NETMASK);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
- error = process_ip_string(file, (char *)new_val->gate_way, GATEWAY);
|
||||
+ error = process_ip_string(ifcfg_file, (char *)new_val->gate_way,
|
||||
+ GATEWAY);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
- error = process_ip_string(file, (char *)new_val->dns_addr, DNS);
|
||||
+ error = process_ip_string(ifcfg_file, (char *)new_val->dns_addr, DNS);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
- fclose(file);
|
||||
+ if (new_val->addr_family == ADDR_FAMILY_IPV6) {
|
||||
+ error = fprintf(nmfile, "\n[ipv6]\n");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ is_ipv6 = 1;
|
||||
+ } else {
|
||||
+ error = fprintf(nmfile, "\n[ipv4]\n");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Now we populate the keyfile format
|
||||
+ */
|
||||
+
|
||||
+ if (new_val->dhcp_enabled) {
|
||||
+ error = kvp_write_file(nmfile, "method", "", "auto");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ } else {
|
||||
+ error = kvp_write_file(nmfile, "method", "", "manual");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Write the configuration for ipaddress, netmask, gateway and
|
||||
+ * name services
|
||||
+ */
|
||||
+ error = process_ip_string_nm(nmfile, (char *)new_val->ip_addr,
|
||||
+ (char *)new_val->sub_net, is_ipv6);
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+
|
||||
+ error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+
|
||||
+ error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+
|
||||
+ fclose(nmfile);
|
||||
+ fclose(ifcfg_file);
|
||||
|
||||
/*
|
||||
* Now that we have populated the configuration file,
|
||||
* invoke the external script to do its magic.
|
||||
*/
|
||||
|
||||
- str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s",
|
||||
- "hv_set_ifconfig", if_file);
|
||||
+ str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s %s",
|
||||
+ "hv_set_ifconfig", if_filename, nm_filename);
|
||||
/*
|
||||
* This is a little overcautious, but it's necessary to suppress some
|
||||
* false warnings from gcc 8.0.1.
|
||||
@@ -1316,14 +1485,16 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
|
||||
if (system(cmd)) {
|
||||
syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s",
|
||||
- cmd, errno, strerror(errno));
|
||||
+ cmd, errno, strerror(errno));
|
||||
return HV_E_FAIL;
|
||||
}
|
||||
return 0;
|
||||
-
|
||||
+setmac_error:
|
||||
+ free(mac_addr);
|
||||
setval_error:
|
||||
syslog(LOG_ERR, "Failed to write config file");
|
||||
- fclose(file);
|
||||
+ fclose(ifcfg_file);
|
||||
+ fclose(nmfile);
|
||||
return error;
|
||||
}
|
||||
|
||||
diff --git a/hv_set_ifconfig.sh b/hv_set_ifconfig.sh
|
||||
index fe7fccf..35aae6f 100644
|
||||
--- a/hv_set_ifconfig.sh
|
||||
+++ b/hv_set_ifconfig.sh
|
||||
@@ -18,12 +18,12 @@
|
||||
#
|
||||
# This example script is based on a RHEL environment.
|
||||
#
|
||||
-# Here is the format of the ip configuration file:
|
||||
+# Here is the ifcfg format of the ip configuration file:
|
||||
#
|
||||
# HWADDR=macaddr
|
||||
# DEVICE=interface name
|
||||
# BOOTPROTO=<protocol> (where <protocol> is "dhcp" if DHCP is configured
|
||||
-# or "none" if no boot-time protocol should be used)
|
||||
+# or "none" if no boot-time protocol should be used)
|
||||
#
|
||||
# IPADDR0=ipaddr1
|
||||
# IPADDR1=ipaddr2
|
||||
@@ -41,6 +41,32 @@
|
||||
# tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as
|
||||
# IPV6NETMASK.
|
||||
#
|
||||
+# Here is the keyfile format of the ip configuration file:
|
||||
+#
|
||||
+# [ethernet]
|
||||
+# mac-address=macaddr
|
||||
+# [connection]
|
||||
+# interface-name=interface name
|
||||
+#
|
||||
+# [ipv4]
|
||||
+# method=<protocol> (where <protocol> is "auto" if DHCP is configured
|
||||
+# or "manual" if no boot-time protocol should be used)
|
||||
+#
|
||||
+# address1=ipaddr1/plen
|
||||
+# address=ipaddr2/plen
|
||||
+#
|
||||
+# gateway=gateway1;gateway2
|
||||
+#
|
||||
+# dns=dns1;
|
||||
+#
|
||||
+# [ipv6]
|
||||
+# address1=ipaddr1/plen
|
||||
+# address2=ipaddr1/plen
|
||||
+#
|
||||
+# gateway=gateway1;gateway2
|
||||
+#
|
||||
+# dns=dns1;dns2
|
||||
+#
|
||||
# The host can specify multiple ipv4 and ipv6 addresses to be
|
||||
# configured for the interface. Furthermore, the configuration
|
||||
# needs to be persistent. A subsequent GET call on the interface
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,41 @@
|
||||
From 5b1094b6e8d7b5314ff32cef741e22bf2904d81f Mon Sep 17 00:00:00 2001
|
||||
From: Till Maas <timaas@redhat.com>
|
||||
Date: Mon, 13 Dec 2021 16:08:42 +0000
|
||||
Subject: [PATCH 04/14] hv_set_ifconfig.sh: Use nmcli commands
|
||||
|
||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-MergeRequest: 9: Synchronize RHEL 9 changes to RHEL 10
|
||||
RH-Jira: RHEL-40107 RHEL-40679
|
||||
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||
RH-Commit: [4/14] 657c30ec2f7f3cf90cd0950e45b2441280ef2581 (mrezanin/centos-git-hyperv-daemons)
|
||||
|
||||
Instead of using deprecated ifup/ifdown commands, use nmcli commands.
|
||||
Taking the connection down is not necessary with NM, so don't do it.
|
||||
|
||||
Resolves: #2026371
|
||||
|
||||
patch_name: hpvd-hv_set_ifconfig.sh-Use-nmcli-commands.patch
|
||||
present_in_specfile: true
|
||||
location_in_specfile: 7
|
||||
---
|
||||
hv_set_ifconfig.sh | 7 ++-----
|
||||
1 file changed, 2 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/hv_set_ifconfig.sh b/hv_set_ifconfig.sh
|
||||
index 3dd064c..5a64efe 100644
|
||||
--- a/hv_set_ifconfig.sh
|
||||
+++ b/hv_set_ifconfig.sh
|
||||
@@ -57,8 +57,5 @@ echo "ONBOOT=yes" >> $1
|
||||
|
||||
cp $1 /etc/sysconfig/network-scripts/
|
||||
|
||||
-
|
||||
-interface=$(echo $1 | awk -F - '{ print $2 }')
|
||||
-
|
||||
-/sbin/ifdown $interface 2>/dev/null
|
||||
-/sbin/ifup $interface 2>/dev/null
|
||||
+nmcli connection load "/etc/sysconfig/network-scripts/$1"
|
||||
+nmcli connection up filename "/etc/sysconfig/network-scripts/$1"
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,47 @@
|
||||
From 039cd98452fcf585533455c28200d438cda8ed7a Mon Sep 17 00:00:00 2001
|
||||
From: Mohammed Gamal <mgamal@redhat.com>
|
||||
Date: Tue, 8 Nov 2022 16:20:17 +0100
|
||||
Subject: [PATCH 06/14] redhat: hv_set_if_config: Workaround for gateway
|
||||
numbering in NetworkManager
|
||||
|
||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-MergeRequest: 9: Synchronize RHEL 9 changes to RHEL 10
|
||||
RH-Jira: RHEL-40107 RHEL-40679
|
||||
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||
RH-Commit: [6/14] 984b946aea905b94672aead098e73368e6c65fc7 (mrezanin/centos-git-hyperv-daemons)
|
||||
|
||||
Unlike older sysconfig scripts, NetworkManager expects GATEWAYx=ipaddr for all values of x.
|
||||
So the first gateway is GATEWAY0 instead of GATEWAY. Other values should remain unchanged.
|
||||
Workaround this by replacing GATEWAY= with GATEWAY0=.
|
||||
|
||||
A proper fix however, would be to generate NetworkManager keyfiles instead of ifcfg files.
|
||||
That can be done eitter by changing hypervkvpd code to do that or to let the script parse
|
||||
ifcfg files and generate corresponding NetworkManager keyfiles
|
||||
|
||||
Signed-off-by: Mohammed Gamal <mgamal@redhat.com>
|
||||
|
||||
patch_name: hpvd-redhat-hv_set_if_config-Workaround-for-gateway-numbe.patch
|
||||
present_in_specfile: true
|
||||
location_in_specfile: 9
|
||||
---
|
||||
hv_set_ifconfig.sh | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/hv_set_ifconfig.sh b/hv_set_ifconfig.sh
|
||||
index 146829b..fe7fccf 100644
|
||||
--- a/hv_set_ifconfig.sh
|
||||
+++ b/hv_set_ifconfig.sh
|
||||
@@ -54,6 +54,10 @@ echo "IPV6INIT=yes" >> $1
|
||||
echo "PEERDNS=yes" >> $1
|
||||
echo "ONBOOT=yes" >> $1
|
||||
|
||||
+#Unlike older sysconfig scripts, NetworkManager expects GATEWAYx=ipaddr for all values of x.
|
||||
+#So the first gateway is GATEWAY0 instead of GATEWAY. Other values should remain unchanged.
|
||||
+#Workaround this by replacing GATEWAY= with GATEWAY0=.
|
||||
+sed -i "s/GATEWAY=/GATEWAY0=/" $1
|
||||
|
||||
cp $1 /etc/sysconfig/network-scripts/
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,48 @@
|
||||
From b4af57850a0f8171116eacb6e8a565ef009e9c4b Mon Sep 17 00:00:00 2001
|
||||
From: Mohammed Gamal <mgamal@redhat.com>
|
||||
Date: Thu, 17 Nov 2022 18:56:20 +0100
|
||||
Subject: [PATCH 07/14] tools: hv: Remove an extraneous "the"
|
||||
|
||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-MergeRequest: 9: Synchronize RHEL 9 changes to RHEL 10
|
||||
RH-Jira: RHEL-40107 RHEL-40679
|
||||
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||
RH-Commit: [7/14] 55fe13a9967894578468229dc925fb106bce7355 (mrezanin/centos-git-hyperv-daemons)
|
||||
|
||||
commit f15f39fabed2248311607445ddfa6dba63abebb9
|
||||
Author: Jason Wang <wangborong@cdjrlc.com>
|
||||
Date: Thu Aug 11 21:34:33 2022 +0800
|
||||
|
||||
tools: hv: Remove an extraneous "the"
|
||||
|
||||
There are two "the" in the text. Remove one.
|
||||
|
||||
Signed-off-by: Jason Wang <wangborong@cdjrlc.com>
|
||||
Link: https://lore.kernel.org/r/20220811133433.10175-1-wangborong@cdjrlc.com
|
||||
Signed-off-by: Wei Liu <wei.liu@kernel.org>
|
||||
|
||||
Signed-off-by: Mohammed Gamal <mgamal@redhat.com>
|
||||
|
||||
patch_name: hpvd-tools-hv-Remove-an-extraneous-the.patch
|
||||
present_in_specfile: true
|
||||
location_in_specfile: 10
|
||||
---
|
||||
hv_kvp_daemon.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hv_kvp_daemon.c b/hv_kvp_daemon.c
|
||||
index 1e6fd6c..c97c12e 100644
|
||||
--- a/hv_kvp_daemon.c
|
||||
+++ b/hv_kvp_daemon.c
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
/*
|
||||
* KVP protocol: The user mode component first registers with the
|
||||
- * the kernel component. Subsequently, the kernel component requests, data
|
||||
+ * kernel component. Subsequently, the kernel component requests, data
|
||||
* for the specified keys. In response to this message the user mode component
|
||||
* fills in the value corresponding to the specified key. We overload the
|
||||
* sequence field in the cn_msg header to define our KVP message types.
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,54 @@
|
||||
From 1a616ef74b66a45c1e16ec12e46fabfc03613668 Mon Sep 17 00:00:00 2001
|
||||
From: Mohammed Gamal <mgamal@redhat.com>
|
||||
Date: Thu, 17 Nov 2022 18:58:31 +0100
|
||||
Subject: [PATCH 08/14] tools: hv: kvp: remove unnecessary (void*) conversions
|
||||
|
||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-MergeRequest: 9: Synchronize RHEL 9 changes to RHEL 10
|
||||
RH-Jira: RHEL-40107 RHEL-40679
|
||||
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||
RH-Commit: [8/14] 16a5e8f5c4799f6777600cd62b4621e450638f22 (mrezanin/centos-git-hyperv-daemons)
|
||||
|
||||
commit 2258954234db7530e9d86bb32cd6ad54485ff926
|
||||
Author: Zhou jie <zhoujie@nfschina.com>
|
||||
Date: Tue Aug 23 11:45:52 2022 +0800
|
||||
|
||||
tools: hv: kvp: remove unnecessary (void*) conversions
|
||||
|
||||
Remove unnecessary void* type casting.
|
||||
|
||||
Signed-off-by: Zhou jie <zhoujie@nfschina.com>
|
||||
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
|
||||
Link: https://lore.kernel.org/r/20220823034552.8596-1-zhoujie@nfschina.com
|
||||
Signed-off-by: Wei Liu <wei.liu@kernel.org>
|
||||
|
||||
Signed-off-by: Mohammed Gamal <mgamal@redhat.com>
|
||||
|
||||
patch_name: hpvd-tools-hv-kvp-remove-unnecessary-void-conversions.patch
|
||||
present_in_specfile: true
|
||||
location_in_specfile: 11
|
||||
---
|
||||
hv_kvp_daemon.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hv_kvp_daemon.c b/hv_kvp_daemon.c
|
||||
index c97c12e..27f5e7d 100644
|
||||
--- a/hv_kvp_daemon.c
|
||||
+++ b/hv_kvp_daemon.c
|
||||
@@ -772,11 +772,11 @@ static int kvp_process_ip_address(void *addrp,
|
||||
const char *str;
|
||||
|
||||
if (family == AF_INET) {
|
||||
- addr = (struct sockaddr_in *)addrp;
|
||||
+ addr = addrp;
|
||||
str = inet_ntop(family, &addr->sin_addr, tmp, 50);
|
||||
addr_length = INET_ADDRSTRLEN;
|
||||
} else {
|
||||
- addr6 = (struct sockaddr_in6 *)addrp;
|
||||
+ addr6 = addrp;
|
||||
str = inet_ntop(family, &addr6->sin6_addr.s6_addr, tmp, 50);
|
||||
addr_length = INET6_ADDRSTRLEN;
|
||||
}
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,55 @@
|
||||
From 520bfb6b8bc7cedc2dcb602a708c1357faf638b8 Mon Sep 17 00:00:00 2001
|
||||
From: Ani Sinha <anisinha@redhat.com>
|
||||
Date: Wed, 5 Jul 2023 18:44:34 +0530
|
||||
Subject: [PATCH 09/14] vmbus_testing: fix wrong python syntax for integer
|
||||
value comparison
|
||||
|
||||
RH-Author: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-MergeRequest: 9: Synchronize RHEL 9 changes to RHEL 10
|
||||
RH-Jira: RHEL-40107 RHEL-40679
|
||||
RH-Acked-by: Ani Sinha <anisinha@redhat.com>
|
||||
RH-Commit: [9/14] 261dfeef254265a966e7175766f366eaed782454 (mrezanin/centos-git-hyperv-daemons)
|
||||
|
||||
It is incorrect in python to compare integer values using the "is" keyword. The
|
||||
"is" keyword in python is used to compare references to two objects, not their
|
||||
values. Newer version of python3 (version 3.8) throws a warning when such
|
||||
incorrect comparison is made. For value comparison, "==" should be used.
|
||||
|
||||
Fix this in the code and suppress the following warning:
|
||||
|
||||
/usr/sbin/vmbus_testing:167: SyntaxWarning: "is" with a literal. Did you mean "=="?
|
||||
|
||||
Signed-off-by: Ani Sinha <anisinha@redhat.com>
|
||||
|
||||
patch_name: hpvd-vmbus_testing-fix-wrong-python-syntax-for-integer-va.patch
|
||||
present_in_specfile: true
|
||||
location_in_specfile: 12
|
||||
---
|
||||
vmbus_testing | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/vmbus_testing b/vmbus_testing
|
||||
index e721290..4467979 100755
|
||||
--- a/vmbus_testing
|
||||
+++ b/vmbus_testing
|
||||
@@ -164,7 +164,7 @@ def recursive_file_lookup(path, file_map):
|
||||
def get_all_devices_test_status(file_map):
|
||||
|
||||
for device in file_map:
|
||||
- if (get_test_state(locate_state(device, file_map)) is 1):
|
||||
+ if (get_test_state(locate_state(device, file_map)) == 1):
|
||||
print("Testing = ON for: {}"
|
||||
.format(device.split("/")[5]))
|
||||
else:
|
||||
@@ -203,7 +203,7 @@ def write_test_files(path, value):
|
||||
def set_test_state(state_path, state_value, quiet):
|
||||
|
||||
write_test_files(state_path, state_value)
|
||||
- if (get_test_state(state_path) is 1):
|
||||
+ if (get_test_state(state_path) == 1):
|
||||
if (not quiet):
|
||||
print("Testing = ON for device: {}"
|
||||
.format(state_path.split("/")[5]))
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,490 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* An implementation of host to guest copy functionality for Linux.
|
||||
*
|
||||
* Copyright (C) 2023, Microsoft, Inc.
|
||||
*
|
||||
* Author : K. Y. Srinivasan <kys@microsoft.com>
|
||||
* Author : Saurabh Sengar <ssengar@microsoft.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <locale.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
#include <sys/stat.h>
|
||||
#include <linux/hyperv.h>
|
||||
#include <linux/limits.h>
|
||||
#include "vmbus_bufring.h"
|
||||
|
||||
#define ICMSGTYPE_NEGOTIATE 0
|
||||
#define ICMSGTYPE_FCOPY 7
|
||||
|
||||
#define WIN8_SRV_MAJOR 1
|
||||
#define WIN8_SRV_MINOR 1
|
||||
#define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
|
||||
|
||||
#define MAX_FOLDER_NAME 15
|
||||
#define MAX_PATH_LEN 15
|
||||
#define FCOPY_UIO "/sys/bus/vmbus/devices/eb765408-105f-49b6-b4aa-c123b64d17d4/uio"
|
||||
|
||||
#define FCOPY_VER_COUNT 1
|
||||
static const int fcopy_versions[] = {
|
||||
WIN8_SRV_VERSION
|
||||
};
|
||||
|
||||
#define FW_VER_COUNT 1
|
||||
static const int fw_versions[] = {
|
||||
UTIL_FW_VERSION
|
||||
};
|
||||
|
||||
#define HV_RING_SIZE 0x4000 /* 16KB ring buffer size */
|
||||
|
||||
unsigned char desc[HV_RING_SIZE];
|
||||
|
||||
static int target_fd;
|
||||
static char target_fname[PATH_MAX];
|
||||
static unsigned long long filesize;
|
||||
|
||||
static int hv_fcopy_create_file(char *file_name, char *path_name, __u32 flags)
|
||||
{
|
||||
int error = HV_E_FAIL;
|
||||
char *q, *p;
|
||||
|
||||
filesize = 0;
|
||||
p = path_name;
|
||||
snprintf(target_fname, sizeof(target_fname), "%s/%s",
|
||||
path_name, file_name);
|
||||
|
||||
/*
|
||||
* Check to see if the path is already in place; if not,
|
||||
* create if required.
|
||||
*/
|
||||
while ((q = strchr(p, '/')) != NULL) {
|
||||
if (q == p) {
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
*q = '\0';
|
||||
if (access(path_name, F_OK)) {
|
||||
if (flags & CREATE_PATH) {
|
||||
if (mkdir(path_name, 0755)) {
|
||||
syslog(LOG_ERR, "Failed to create %s",
|
||||
path_name);
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
syslog(LOG_ERR, "Invalid path: %s", path_name);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
p = q + 1;
|
||||
*q = '/';
|
||||
}
|
||||
|
||||
if (!access(target_fname, F_OK)) {
|
||||
syslog(LOG_INFO, "File: %s exists", target_fname);
|
||||
if (!(flags & OVER_WRITE)) {
|
||||
error = HV_ERROR_ALREADY_EXISTS;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
target_fd = open(target_fname,
|
||||
O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0744);
|
||||
if (target_fd == -1) {
|
||||
syslog(LOG_INFO, "Open Failed: %s", strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
done:
|
||||
if (error)
|
||||
target_fname[0] = '\0';
|
||||
return error;
|
||||
}
|
||||
|
||||
/* copy the data into the file */
|
||||
static int hv_copy_data(struct hv_do_fcopy *cpmsg)
|
||||
{
|
||||
ssize_t len;
|
||||
int ret = 0;
|
||||
|
||||
len = pwrite(target_fd, cpmsg->data, cpmsg->size, cpmsg->offset);
|
||||
|
||||
filesize += cpmsg->size;
|
||||
if (len != cpmsg->size) {
|
||||
switch (errno) {
|
||||
case ENOSPC:
|
||||
ret = HV_ERROR_DISK_FULL;
|
||||
break;
|
||||
default:
|
||||
ret = HV_E_FAIL;
|
||||
break;
|
||||
}
|
||||
syslog(LOG_ERR, "pwrite failed to write %llu bytes: %ld (%s)",
|
||||
filesize, (long)len, strerror(errno));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int hv_copy_finished(void)
|
||||
{
|
||||
close(target_fd);
|
||||
target_fname[0] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_usage(char *argv[])
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [options]\n"
|
||||
"Options are:\n"
|
||||
" -n, --no-daemon stay in foreground, don't daemonize\n"
|
||||
" -h, --help print this help\n", argv[0]);
|
||||
}
|
||||
|
||||
static bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, unsigned char *buf,
|
||||
unsigned int buflen, const int *fw_version, int fw_vercnt,
|
||||
const int *srv_version, int srv_vercnt,
|
||||
int *nego_fw_version, int *nego_srv_version)
|
||||
{
|
||||
int icframe_major, icframe_minor;
|
||||
int icmsg_major, icmsg_minor;
|
||||
int fw_major, fw_minor;
|
||||
int srv_major, srv_minor;
|
||||
int i, j;
|
||||
bool found_match = false;
|
||||
struct icmsg_negotiate *negop;
|
||||
|
||||
/* Check that there's enough space for icframe_vercnt, icmsg_vercnt */
|
||||
if (buflen < ICMSG_HDR + offsetof(struct icmsg_negotiate, reserved)) {
|
||||
syslog(LOG_ERR, "Invalid icmsg negotiate");
|
||||
return false;
|
||||
}
|
||||
|
||||
icmsghdrp->icmsgsize = 0x10;
|
||||
negop = (struct icmsg_negotiate *)&buf[ICMSG_HDR];
|
||||
|
||||
icframe_major = negop->icframe_vercnt;
|
||||
icframe_minor = 0;
|
||||
|
||||
icmsg_major = negop->icmsg_vercnt;
|
||||
icmsg_minor = 0;
|
||||
|
||||
/* Validate negop packet */
|
||||
if (icframe_major > IC_VERSION_NEGOTIATION_MAX_VER_COUNT ||
|
||||
icmsg_major > IC_VERSION_NEGOTIATION_MAX_VER_COUNT ||
|
||||
ICMSG_NEGOTIATE_PKT_SIZE(icframe_major, icmsg_major) > buflen) {
|
||||
syslog(LOG_ERR, "Invalid icmsg negotiate - icframe_major: %u, icmsg_major: %u\n",
|
||||
icframe_major, icmsg_major);
|
||||
goto fw_error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Select the framework version number we will
|
||||
* support.
|
||||
*/
|
||||
|
||||
for (i = 0; i < fw_vercnt; i++) {
|
||||
fw_major = (fw_version[i] >> 16);
|
||||
fw_minor = (fw_version[i] & 0xFFFF);
|
||||
|
||||
for (j = 0; j < negop->icframe_vercnt; j++) {
|
||||
if (negop->icversion_data[j].major == fw_major &&
|
||||
negop->icversion_data[j].minor == fw_minor) {
|
||||
icframe_major = negop->icversion_data[j].major;
|
||||
icframe_minor = negop->icversion_data[j].minor;
|
||||
found_match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_match)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found_match)
|
||||
goto fw_error;
|
||||
|
||||
found_match = false;
|
||||
|
||||
for (i = 0; i < srv_vercnt; i++) {
|
||||
srv_major = (srv_version[i] >> 16);
|
||||
srv_minor = (srv_version[i] & 0xFFFF);
|
||||
|
||||
for (j = negop->icframe_vercnt;
|
||||
(j < negop->icframe_vercnt + negop->icmsg_vercnt);
|
||||
j++) {
|
||||
if (negop->icversion_data[j].major == srv_major &&
|
||||
negop->icversion_data[j].minor == srv_minor) {
|
||||
icmsg_major = negop->icversion_data[j].major;
|
||||
icmsg_minor = negop->icversion_data[j].minor;
|
||||
found_match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found_match)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Respond with the framework and service
|
||||
* version numbers we can support.
|
||||
*/
|
||||
fw_error:
|
||||
if (!found_match) {
|
||||
negop->icframe_vercnt = 0;
|
||||
negop->icmsg_vercnt = 0;
|
||||
} else {
|
||||
negop->icframe_vercnt = 1;
|
||||
negop->icmsg_vercnt = 1;
|
||||
}
|
||||
|
||||
if (nego_fw_version)
|
||||
*nego_fw_version = (icframe_major << 16) | icframe_minor;
|
||||
|
||||
if (nego_srv_version)
|
||||
*nego_srv_version = (icmsg_major << 16) | icmsg_minor;
|
||||
|
||||
negop->icversion_data[0].major = icframe_major;
|
||||
negop->icversion_data[0].minor = icframe_minor;
|
||||
negop->icversion_data[1].major = icmsg_major;
|
||||
negop->icversion_data[1].minor = icmsg_minor;
|
||||
|
||||
return found_match;
|
||||
}
|
||||
|
||||
static void wcstoutf8(char *dest, const __u16 *src, size_t dest_size)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
while (len < dest_size) {
|
||||
if (src[len] < 0x80)
|
||||
dest[len++] = (char)(*src++);
|
||||
else
|
||||
dest[len++] = 'X';
|
||||
}
|
||||
|
||||
dest[len] = '\0';
|
||||
}
|
||||
|
||||
static int hv_fcopy_start(struct hv_start_fcopy *smsg_in)
|
||||
{
|
||||
setlocale(LC_ALL, "en_US.utf8");
|
||||
size_t file_size, path_size;
|
||||
char *file_name, *path_name;
|
||||
char *in_file_name = (char *)smsg_in->file_name;
|
||||
char *in_path_name = (char *)smsg_in->path_name;
|
||||
|
||||
file_size = wcstombs(NULL, (const wchar_t *restrict)in_file_name, 0) + 1;
|
||||
path_size = wcstombs(NULL, (const wchar_t *restrict)in_path_name, 0) + 1;
|
||||
|
||||
file_name = (char *)malloc(file_size * sizeof(char));
|
||||
path_name = (char *)malloc(path_size * sizeof(char));
|
||||
|
||||
wcstoutf8(file_name, (__u16 *)in_file_name, file_size);
|
||||
wcstoutf8(path_name, (__u16 *)in_path_name, path_size);
|
||||
|
||||
return hv_fcopy_create_file(file_name, path_name, smsg_in->copy_flags);
|
||||
}
|
||||
|
||||
static int hv_fcopy_send_data(struct hv_fcopy_hdr *fcopy_msg, int recvlen)
|
||||
{
|
||||
int operation = fcopy_msg->operation;
|
||||
|
||||
/*
|
||||
* The strings sent from the host are encoded in
|
||||
* utf16; convert it to utf8 strings.
|
||||
* The host assures us that the utf16 strings will not exceed
|
||||
* the max lengths specified. We will however, reserve room
|
||||
* for the string terminating character - in the utf16s_utf8s()
|
||||
* function we limit the size of the buffer where the converted
|
||||
* string is placed to W_MAX_PATH -1 to guarantee
|
||||
* that the strings can be properly terminated!
|
||||
*/
|
||||
|
||||
switch (operation) {
|
||||
case START_FILE_COPY:
|
||||
return hv_fcopy_start((struct hv_start_fcopy *)fcopy_msg);
|
||||
case WRITE_TO_FILE:
|
||||
return hv_copy_data((struct hv_do_fcopy *)fcopy_msg);
|
||||
case COMPLETE_FCOPY:
|
||||
return hv_copy_finished();
|
||||
}
|
||||
|
||||
return HV_E_FAIL;
|
||||
}
|
||||
|
||||
/* process the packet recv from host */
|
||||
static int fcopy_pkt_process(struct vmbus_br *txbr)
|
||||
{
|
||||
int ret, offset, pktlen;
|
||||
int fcopy_srv_version;
|
||||
const struct vmbus_chanpkt_hdr *pkt;
|
||||
struct hv_fcopy_hdr *fcopy_msg;
|
||||
struct icmsg_hdr *icmsghdr;
|
||||
|
||||
pkt = (const struct vmbus_chanpkt_hdr *)desc;
|
||||
offset = pkt->hlen << 3;
|
||||
pktlen = (pkt->tlen << 3) - offset;
|
||||
icmsghdr = (struct icmsg_hdr *)&desc[offset + sizeof(struct vmbuspipe_hdr)];
|
||||
icmsghdr->status = HV_E_FAIL;
|
||||
|
||||
if (icmsghdr->icmsgtype == ICMSGTYPE_NEGOTIATE) {
|
||||
if (vmbus_prep_negotiate_resp(icmsghdr, desc + offset, pktlen, fw_versions,
|
||||
FW_VER_COUNT, fcopy_versions, FCOPY_VER_COUNT,
|
||||
NULL, &fcopy_srv_version)) {
|
||||
syslog(LOG_INFO, "FCopy IC version %d.%d",
|
||||
fcopy_srv_version >> 16, fcopy_srv_version & 0xFFFF);
|
||||
icmsghdr->status = 0;
|
||||
}
|
||||
} else if (icmsghdr->icmsgtype == ICMSGTYPE_FCOPY) {
|
||||
/* Ensure recvlen is big enough to contain hv_fcopy_hdr */
|
||||
if (pktlen < ICMSG_HDR + sizeof(struct hv_fcopy_hdr)) {
|
||||
syslog(LOG_ERR, "Invalid Fcopy hdr. Packet length too small: %u",
|
||||
pktlen);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
fcopy_msg = (struct hv_fcopy_hdr *)&desc[offset + ICMSG_HDR];
|
||||
icmsghdr->status = hv_fcopy_send_data(fcopy_msg, pktlen);
|
||||
}
|
||||
|
||||
icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
|
||||
ret = rte_vmbus_chan_send(txbr, 0x6, desc + offset, pktlen, 0);
|
||||
if (ret) {
|
||||
syslog(LOG_ERR, "Write to ringbuffer failed err: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fcopy_get_first_folder(char *path, char *chan_no)
|
||||
{
|
||||
DIR *dir = opendir(path);
|
||||
struct dirent *entry;
|
||||
|
||||
if (!dir) {
|
||||
syslog(LOG_ERR, "Failed to open directory (errno=%s).\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (entry->d_type == DT_DIR && strcmp(entry->d_name, ".") != 0 &&
|
||||
strcmp(entry->d_name, "..") != 0) {
|
||||
strcpy(chan_no, entry->d_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int fcopy_fd = -1, tmp = 1;
|
||||
int daemonize = 1, long_index = 0, opt, ret = -EINVAL;
|
||||
struct vmbus_br txbr, rxbr;
|
||||
void *ring;
|
||||
uint32_t len = HV_RING_SIZE;
|
||||
char uio_name[MAX_FOLDER_NAME] = {0};
|
||||
char uio_dev_path[MAX_PATH_LEN] = {0};
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{"no-daemon", no_argument, 0, 'n' },
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "hn", long_options,
|
||||
&long_index)) != -1) {
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
daemonize = 0;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
print_usage(argv);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (daemonize && daemon(1, 0)) {
|
||||
syslog(LOG_ERR, "daemon() failed; error: %s", strerror(errno));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
openlog("HV_UIO_FCOPY", 0, LOG_USER);
|
||||
syslog(LOG_INFO, "starting; pid is:%d", getpid());
|
||||
|
||||
fcopy_get_first_folder(FCOPY_UIO, uio_name);
|
||||
snprintf(uio_dev_path, sizeof(uio_dev_path), "/dev/%s", uio_name);
|
||||
fcopy_fd = open(uio_dev_path, O_RDWR);
|
||||
|
||||
if (fcopy_fd < 0) {
|
||||
syslog(LOG_ERR, "open %s failed; error: %d %s",
|
||||
uio_dev_path, errno, strerror(errno));
|
||||
ret = fcopy_fd;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ring = vmbus_uio_map(&fcopy_fd, HV_RING_SIZE);
|
||||
if (!ring) {
|
||||
ret = errno;
|
||||
syslog(LOG_ERR, "mmap ringbuffer failed; error: %d %s", ret, strerror(ret));
|
||||
goto close;
|
||||
}
|
||||
vmbus_br_setup(&txbr, ring, HV_RING_SIZE);
|
||||
vmbus_br_setup(&rxbr, (char *)ring + HV_RING_SIZE, HV_RING_SIZE);
|
||||
|
||||
rxbr.vbr->imask = 0;
|
||||
|
||||
while (1) {
|
||||
/*
|
||||
* In this loop we process fcopy messages after the
|
||||
* handshake is complete.
|
||||
*/
|
||||
ret = pread(fcopy_fd, &tmp, sizeof(int), 0);
|
||||
if (ret < 0) {
|
||||
syslog(LOG_ERR, "pread failed: %s", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
len = HV_RING_SIZE;
|
||||
ret = rte_vmbus_chan_recv_raw(&rxbr, desc, &len);
|
||||
if (unlikely(ret <= 0)) {
|
||||
/* This indicates a failure to communicate (or worse) */
|
||||
syslog(LOG_ERR, "VMBus channel recv error: %d", ret);
|
||||
} else {
|
||||
ret = fcopy_pkt_process(&txbr);
|
||||
if (ret < 0)
|
||||
goto close;
|
||||
|
||||
/* Signal host */
|
||||
if ((write(fcopy_fd, &tmp, sizeof(int))) != sizeof(int)) {
|
||||
ret = errno;
|
||||
syslog(LOG_ERR, "Signal to host failed: %s\n", strerror(ret));
|
||||
goto close;
|
||||
}
|
||||
}
|
||||
}
|
||||
close:
|
||||
close(fcopy_fd);
|
||||
exit:
|
||||
return ret;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
# This example script retrieves the DHCP state of a given interface.
|
||||
# In the interest of keeping the KVP daemon code free of distro specific
|
||||
# information; the kvp daemon code invokes this external script to gather
|
||||
# DHCP setting for the specific interface.
|
||||
#
|
||||
# Input: Name of the interface
|
||||
#
|
||||
# Output: The script prints the string "Enabled" to stdout to indicate
|
||||
# that DHCP is enabled on the interface. If DHCP is not enabled,
|
||||
# the script prints the string "Disabled" to stdout.
|
||||
#
|
||||
# Each Distro is expected to implement this script in a distro specific
|
||||
# fashion. For instance, on Distros that ship with Network Manager enabled,
|
||||
# this script can be based on the Network Manager APIs for retrieving DHCP
|
||||
# information.
|
||||
|
||||
if_file="/etc/sysconfig/network-scripts/ifcfg-"$1
|
||||
|
||||
dhcp=$(grep "dhcp" $if_file 2>/dev/null)
|
||||
|
||||
if [ "$dhcp" != "" ];
|
||||
then
|
||||
echo "Enabled"
|
||||
else
|
||||
echo "Disabled"
|
||||
fi
|
@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
# This example script parses /etc/resolv.conf to retrive DNS information.
|
||||
# In the interest of keeping the KVP daemon code free of distro specific
|
||||
# information; the kvp daemon code invokes this external script to gather
|
||||
# DNS information.
|
||||
# This script is expected to print the nameserver values to stdout.
|
||||
# Each Distro is expected to implement this script in a distro specific
|
||||
# fashion. For instance on Distros that ship with Network Manager enabled,
|
||||
# this script can be based on the Network Manager APIs for retrieving DNS
|
||||
# entries.
|
||||
|
||||
cat /etc/resolv.conf 2>/dev/null | awk '/^nameserver/ { print $2 }'
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,65 @@
|
||||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
# This example script activates an interface based on the specified
|
||||
# configuration.
|
||||
#
|
||||
# In the interest of keeping the KVP daemon code free of distro specific
|
||||
# information; the kvp daemon code invokes this external script to configure
|
||||
# the interface.
|
||||
#
|
||||
# The only argument to this script is the configuration file that is to
|
||||
# be used to configure the interface.
|
||||
#
|
||||
# Each Distro is expected to implement this script in a distro specific
|
||||
# fashion. For instance, on Distros that ship with Network Manager enabled,
|
||||
# this script can be based on the Network Manager APIs for configuring the
|
||||
# interface.
|
||||
#
|
||||
# This example script is based on a RHEL environment.
|
||||
#
|
||||
# Here is the format of the ip configuration file:
|
||||
#
|
||||
# HWADDR=macaddr
|
||||
# DEVICE=interface name
|
||||
# BOOTPROTO=<protocol> (where <protocol> is "dhcp" if DHCP is configured
|
||||
# or "none" if no boot-time protocol should be used)
|
||||
#
|
||||
# IPADDR0=ipaddr1
|
||||
# IPADDR1=ipaddr2
|
||||
# IPADDRx=ipaddry (where y = x + 1)
|
||||
#
|
||||
# NETMASK0=netmask1
|
||||
# NETMASKx=netmasky (where y = x + 1)
|
||||
#
|
||||
# GATEWAY=ipaddr1
|
||||
# GATEWAYx=ipaddry (where y = x + 1)
|
||||
#
|
||||
# DNSx=ipaddrx (where first DNS address is tagged as DNS1 etc)
|
||||
#
|
||||
# IPV6 addresses will be tagged as IPV6ADDR, IPV6 gateway will be
|
||||
# tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as
|
||||
# IPV6NETMASK.
|
||||
#
|
||||
# The host can specify multiple ipv4 and ipv6 addresses to be
|
||||
# configured for the interface. Furthermore, the configuration
|
||||
# needs to be persistent. A subsequent GET call on the interface
|
||||
# is expected to return the configuration that is set via the SET
|
||||
# call.
|
||||
#
|
||||
|
||||
|
||||
|
||||
echo "IPV6INIT=yes" >> $1
|
||||
echo "NM_CONTROLLED=no" >> $1
|
||||
echo "PEERDNS=yes" >> $1
|
||||
echo "ONBOOT=yes" >> $1
|
||||
|
||||
|
||||
cp $1 /etc/sysconfig/network-scripts/
|
||||
|
||||
|
||||
interface=$(echo $1 | awk -F - '{ print $2 }')
|
||||
|
||||
/sbin/ifdown $interface 2>/dev/null
|
||||
/sbin/ifup $interface 2>/dev/null
|
@ -0,0 +1,355 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* An implementation of the host initiated guest snapshot for Hyper-V.
|
||||
*
|
||||
* Copyright (C) 2013, Microsoft, Inc.
|
||||
* Author : K. Y. Srinivasan <kys@microsoft.com>
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <mntent.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/major.h>
|
||||
#include <linux/hyperv.h>
|
||||
#include <syslog.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <dirent.h>
|
||||
|
||||
static bool fs_frozen;
|
||||
|
||||
/* Don't use syslog() in the function since that can cause write to disk */
|
||||
static int vss_do_freeze(char *dir, unsigned int cmd)
|
||||
{
|
||||
int ret, fd = open(dir, O_RDONLY);
|
||||
|
||||
if (fd < 0)
|
||||
return 1;
|
||||
|
||||
ret = ioctl(fd, cmd, 0);
|
||||
|
||||
/*
|
||||
* If a partition is mounted more than once, only the first
|
||||
* FREEZE/THAW can succeed and the later ones will get
|
||||
* EBUSY/EINVAL respectively: there could be 2 cases:
|
||||
* 1) a user may mount the same partition to different directories
|
||||
* by mistake or on purpose;
|
||||
* 2) The subvolume of btrfs appears to have the same partition
|
||||
* mounted more than once.
|
||||
*/
|
||||
if (ret) {
|
||||
if ((cmd == FIFREEZE && errno == EBUSY) ||
|
||||
(cmd == FITHAW && errno == EINVAL)) {
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return !!ret;
|
||||
}
|
||||
|
||||
static bool is_dev_loop(const char *blkname)
|
||||
{
|
||||
char *buffer;
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
bool ret = false;
|
||||
|
||||
buffer = malloc(PATH_MAX);
|
||||
if (!buffer) {
|
||||
syslog(LOG_ERR, "Can't allocate memory!");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
snprintf(buffer, PATH_MAX, "%s/loop", blkname);
|
||||
if (!access(buffer, R_OK | X_OK)) {
|
||||
ret = true;
|
||||
goto free_buffer;
|
||||
} else if (errno != ENOENT) {
|
||||
syslog(LOG_ERR, "Can't access: %s; error:%d %s!",
|
||||
buffer, errno, strerror(errno));
|
||||
}
|
||||
|
||||
snprintf(buffer, PATH_MAX, "%s/slaves", blkname);
|
||||
dir = opendir(buffer);
|
||||
if (!dir) {
|
||||
if (errno != ENOENT)
|
||||
syslog(LOG_ERR, "Can't opendir: %s; error:%d %s!",
|
||||
buffer, errno, strerror(errno));
|
||||
goto free_buffer;
|
||||
}
|
||||
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (strcmp(entry->d_name, ".") == 0 ||
|
||||
strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
snprintf(buffer, PATH_MAX, "%s/slaves/%s", blkname,
|
||||
entry->d_name);
|
||||
if (is_dev_loop(buffer)) {
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
free_buffer:
|
||||
free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vss_operate(int operation)
|
||||
{
|
||||
char match[] = "/dev/";
|
||||
FILE *mounts;
|
||||
struct mntent *ent;
|
||||
struct stat sb;
|
||||
char errdir[1024] = {0};
|
||||
char blkdir[23]; /* /sys/dev/block/XXX:XXX */
|
||||
unsigned int cmd;
|
||||
int error = 0, root_seen = 0, save_errno = 0;
|
||||
|
||||
switch (operation) {
|
||||
case VSS_OP_FREEZE:
|
||||
cmd = FIFREEZE;
|
||||
break;
|
||||
case VSS_OP_THAW:
|
||||
cmd = FITHAW;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
mounts = setmntent("/proc/mounts", "r");
|
||||
if (mounts == NULL)
|
||||
return -1;
|
||||
|
||||
while ((ent = getmntent(mounts))) {
|
||||
if (strncmp(ent->mnt_fsname, match, strlen(match)))
|
||||
continue;
|
||||
if (stat(ent->mnt_fsname, &sb)) {
|
||||
syslog(LOG_ERR, "Can't stat: %s; error:%d %s!",
|
||||
ent->mnt_fsname, errno, strerror(errno));
|
||||
} else {
|
||||
sprintf(blkdir, "/sys/dev/block/%d:%d",
|
||||
major(sb.st_rdev), minor(sb.st_rdev));
|
||||
if (is_dev_loop(blkdir))
|
||||
continue;
|
||||
}
|
||||
if (hasmntopt(ent, MNTOPT_RO) != NULL)
|
||||
continue;
|
||||
if (strcmp(ent->mnt_type, "vfat") == 0)
|
||||
continue;
|
||||
if (strcmp(ent->mnt_dir, "/") == 0) {
|
||||
root_seen = 1;
|
||||
continue;
|
||||
}
|
||||
error |= vss_do_freeze(ent->mnt_dir, cmd);
|
||||
if (operation == VSS_OP_FREEZE) {
|
||||
if (error)
|
||||
goto err;
|
||||
fs_frozen = true;
|
||||
}
|
||||
}
|
||||
|
||||
endmntent(mounts);
|
||||
|
||||
if (root_seen) {
|
||||
error |= vss_do_freeze("/", cmd);
|
||||
if (operation == VSS_OP_FREEZE) {
|
||||
if (error)
|
||||
goto err;
|
||||
fs_frozen = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (operation == VSS_OP_THAW && !error)
|
||||
fs_frozen = false;
|
||||
|
||||
goto out;
|
||||
err:
|
||||
save_errno = errno;
|
||||
if (ent) {
|
||||
strncpy(errdir, ent->mnt_dir, sizeof(errdir)-1);
|
||||
endmntent(mounts);
|
||||
}
|
||||
vss_operate(VSS_OP_THAW);
|
||||
fs_frozen = false;
|
||||
/* Call syslog after we thaw all filesystems */
|
||||
if (ent)
|
||||
syslog(LOG_ERR, "FREEZE of %s failed; error:%d %s",
|
||||
errdir, save_errno, strerror(save_errno));
|
||||
else
|
||||
syslog(LOG_ERR, "FREEZE of / failed; error:%d %s", save_errno,
|
||||
strerror(save_errno));
|
||||
out:
|
||||
return error;
|
||||
}
|
||||
|
||||
void print_usage(char *argv[])
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [options]\n"
|
||||
"Options are:\n"
|
||||
" -n, --no-daemon stay in foreground, don't daemonize\n"
|
||||
" -h, --help print this help\n", argv[0]);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int vss_fd = -1, len;
|
||||
int error;
|
||||
struct pollfd pfd;
|
||||
int op;
|
||||
struct hv_vss_msg vss_msg[1];
|
||||
int daemonize = 1, long_index = 0, opt;
|
||||
int in_handshake;
|
||||
__u32 kernel_modver;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"help", no_argument, 0, 'h' },
|
||||
{"no-daemon", no_argument, 0, 'n' },
|
||||
{0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "hn", long_options,
|
||||
&long_index)) != -1) {
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
daemonize = 0;
|
||||
break;
|
||||
case 'h':
|
||||
print_usage(argv);
|
||||
exit(0);
|
||||
default:
|
||||
print_usage(argv);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (daemonize && daemon(1, 0))
|
||||
return 1;
|
||||
|
||||
openlog("Hyper-V VSS", 0, LOG_USER);
|
||||
syslog(LOG_INFO, "VSS starting; pid is:%d", getpid());
|
||||
|
||||
reopen_vss_fd:
|
||||
if (vss_fd != -1)
|
||||
close(vss_fd);
|
||||
if (fs_frozen) {
|
||||
if (vss_operate(VSS_OP_THAW) || fs_frozen) {
|
||||
syslog(LOG_ERR, "failed to thaw file system: err=%d",
|
||||
errno);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
in_handshake = 1;
|
||||
vss_fd = open("/dev/vmbus/hv_vss", O_RDWR);
|
||||
if (vss_fd < 0) {
|
||||
syslog(LOG_ERR, "open /dev/vmbus/hv_vss failed; error: %d %s",
|
||||
errno, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/*
|
||||
* Register ourselves with the kernel.
|
||||
*/
|
||||
vss_msg->vss_hdr.operation = VSS_OP_REGISTER1;
|
||||
|
||||
len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
|
||||
if (len < 0) {
|
||||
syslog(LOG_ERR, "registration to kernel failed; error: %d %s",
|
||||
errno, strerror(errno));
|
||||
close(vss_fd);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pfd.fd = vss_fd;
|
||||
|
||||
while (1) {
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
|
||||
if (poll(&pfd, 1, -1) < 0) {
|
||||
syslog(LOG_ERR, "poll failed; error:%d %s", errno, strerror(errno));
|
||||
if (errno == EINVAL) {
|
||||
close(vss_fd);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
len = read(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
|
||||
|
||||
if (in_handshake) {
|
||||
if (len != sizeof(kernel_modver)) {
|
||||
syslog(LOG_ERR, "invalid version negotiation");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
kernel_modver = *(__u32 *)vss_msg;
|
||||
in_handshake = 0;
|
||||
syslog(LOG_INFO, "VSS: kernel module version: %d",
|
||||
kernel_modver);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (len != sizeof(struct hv_vss_msg)) {
|
||||
syslog(LOG_ERR, "read failed; error:%d %s",
|
||||
errno, strerror(errno));
|
||||
goto reopen_vss_fd;
|
||||
}
|
||||
|
||||
op = vss_msg->vss_hdr.operation;
|
||||
error = HV_S_OK;
|
||||
|
||||
switch (op) {
|
||||
case VSS_OP_FREEZE:
|
||||
case VSS_OP_THAW:
|
||||
error = vss_operate(op);
|
||||
syslog(LOG_INFO, "VSS: op=%s: %s\n",
|
||||
op == VSS_OP_FREEZE ? "FREEZE" : "THAW",
|
||||
error ? "failed" : "succeeded");
|
||||
|
||||
if (error) {
|
||||
error = HV_E_FAIL;
|
||||
syslog(LOG_ERR, "op=%d failed!", op);
|
||||
syslog(LOG_ERR, "report it with these files:");
|
||||
syslog(LOG_ERR, "/etc/fstab and /proc/mounts");
|
||||
}
|
||||
break;
|
||||
case VSS_OP_HOT_BACKUP:
|
||||
syslog(LOG_INFO, "VSS: op=CHECK HOT BACKUP\n");
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_ERR, "Illegal op:%d\n", op);
|
||||
}
|
||||
|
||||
/*
|
||||
* The write() may return an error due to the faked VSS_OP_THAW
|
||||
* message upon hibernation. Ignore the error by resetting the
|
||||
* dev file, i.e. closing and re-opening it.
|
||||
*/
|
||||
vss_msg->error = error;
|
||||
len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg));
|
||||
if (len != sizeof(struct hv_vss_msg)) {
|
||||
syslog(LOG_ERR, "write failed; error: %d %s", errno,
|
||||
strerror(errno));
|
||||
goto reopen_vss_fd;
|
||||
}
|
||||
}
|
||||
|
||||
close(vss_fd);
|
||||
exit(0);
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
[Unit]
|
||||
Description=Hyper-V FCOPY UIO daemon
|
||||
ConditionPathExists=/sys/bus/vmbus/devices/eb765408-105f-49b6-b4aa-c123b64d17d4/
|
||||
IgnoreOnIsolate=1
|
||||
|
||||
[Service]
|
||||
ExecStartPre=/bin/sh -c '[ ! -d /sys/bus/vmbus/devices/eb765408-105f-49b6-b4aa-c123b64d17d4/uio ] && modprobe uio_hv_generic && echo 34d14be3-dee4-41c8-9ae7-6b174977c192 > /sys/bus/vmbus/drivers/uio_hv_generic/new_id ||:'
|
||||
ExecStart=/usr/sbin/hv_fcopy_uio_daemon -n
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -0,0 +1 @@
|
||||
SUBSYSTEM=="misc", KERNEL=="vmbus/hv_kvp", TAG+="systemd", ENV{SYSTEMD_WANTS}+="hypervkvpd.service"
|
@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=Hyper-V KVP daemon
|
||||
ConditionVirtualization=microsoft
|
||||
BindsTo=sys-devices-virtual-misc-vmbus\x21hv_kvp.device
|
||||
After=sys-devices-virtual-misc-vmbus\x21hv_kvp.device
|
||||
RequiresMountsFor=/var/lib/hyperv
|
||||
Before=cloud-init-local.service
|
||||
IgnoreOnIsolate=1
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/sbin/hypervkvpd -n
|
@ -0,0 +1 @@
|
||||
SUBSYSTEM=="misc", KERNEL=="vmbus/hv_vss", TAG+="systemd", ENV{SYSTEMD_WANTS}+="hypervvssd.service"
|
@ -0,0 +1,8 @@
|
||||
[Unit]
|
||||
Description=Hyper-V VSS daemon
|
||||
ConditionVirtualization=microsoft
|
||||
BindsTo=sys-devices-virtual-misc-vmbus\x21hv_vss.device
|
||||
IgnoreOnIsolate=1
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/sbin/hypervvssd -n
|
@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
import os
|
||||
from optparse import OptionParser
|
||||
|
||||
help_msg = "print verbose messages. Try -vv, -vvv for more verbose messages"
|
||||
parser = OptionParser()
|
||||
parser.add_option(
|
||||
"-v", "--verbose", dest="verbose", help=help_msg, action="count")
|
||||
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
verbose = 0
|
||||
if options.verbose is not None:
|
||||
verbose = options.verbose
|
||||
|
||||
vmbus_sys_path = '/sys/bus/vmbus/devices'
|
||||
if not os.path.isdir(vmbus_sys_path):
|
||||
print("%s doesn't exist: exiting..." % vmbus_sys_path)
|
||||
exit(-1)
|
||||
|
||||
vmbus_dev_dict = {
|
||||
'{0e0b6031-5213-4934-818b-38d90ced39db}': '[Operating system shutdown]',
|
||||
'{9527e630-d0ae-497b-adce-e80ab0175caf}': '[Time Synchronization]',
|
||||
'{57164f39-9115-4e78-ab55-382f3bd5422d}': '[Heartbeat]',
|
||||
'{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}': '[Data Exchange]',
|
||||
'{35fa2e29-ea23-4236-96ae-3a6ebacba440}': '[Backup (volume checkpoint)]',
|
||||
'{34d14be3-dee4-41c8-9ae7-6b174977c192}': '[Guest services]',
|
||||
'{525074dc-8985-46e2-8057-a307dc18a502}': '[Dynamic Memory]',
|
||||
'{cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}': 'Synthetic mouse',
|
||||
'{f912ad6d-2b17-48ea-bd65-f927a61c7684}': 'Synthetic keyboard',
|
||||
'{da0a7802-e377-4aac-8e77-0558eb1073f8}': 'Synthetic framebuffer adapter',
|
||||
'{f8615163-df3e-46c5-913f-f2d2f965ed0e}': 'Synthetic network adapter',
|
||||
'{32412632-86cb-44a2-9b5c-50d1417354f5}': 'Synthetic IDE Controller',
|
||||
'{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}': 'Synthetic SCSI Controller',
|
||||
'{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}': 'Synthetic fiber channel adapter',
|
||||
'{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}': 'Synthetic RDMA adapter',
|
||||
'{44c4f61d-4444-4400-9d52-802e27ede19f}': 'PCI Express pass-through',
|
||||
'{276aacf4-ac15-426c-98dd-7521ad3f01fe}': '[Reserved system device]',
|
||||
'{f8e65716-3cb3-4a06-9a60-1889c5cccab5}': '[Reserved system device]',
|
||||
'{3375baf4-9e15-4b30-b765-67acb10d607b}': '[Reserved system device]',
|
||||
}
|
||||
|
||||
|
||||
def get_vmbus_dev_attr(dev_name, attr):
|
||||
try:
|
||||
f = open('%s/%s/%s' % (vmbus_sys_path, dev_name, attr), 'r')
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
except IOError:
|
||||
lines = []
|
||||
|
||||
return lines
|
||||
|
||||
|
||||
class VMBus_Dev:
|
||||
pass
|
||||
|
||||
|
||||
vmbus_dev_list = []
|
||||
|
||||
for f in os.listdir(vmbus_sys_path):
|
||||
vmbus_id = get_vmbus_dev_attr(f, 'id')[0].strip()
|
||||
class_id = get_vmbus_dev_attr(f, 'class_id')[0].strip()
|
||||
device_id = get_vmbus_dev_attr(f, 'device_id')[0].strip()
|
||||
dev_desc = vmbus_dev_dict.get(class_id, 'Unknown')
|
||||
|
||||
chn_vp_mapping = get_vmbus_dev_attr(f, 'channel_vp_mapping')
|
||||
chn_vp_mapping = [c.strip() for c in chn_vp_mapping]
|
||||
chn_vp_mapping = sorted(
|
||||
chn_vp_mapping, key=lambda c: int(c.split(':')[0]))
|
||||
|
||||
chn_vp_mapping = [
|
||||
'\tRel_ID=%s, target_cpu=%s' %
|
||||
(c.split(':')[0], c.split(':')[1]) for c in chn_vp_mapping
|
||||
]
|
||||
d = VMBus_Dev()
|
||||
d.sysfs_path = '%s/%s' % (vmbus_sys_path, f)
|
||||
d.vmbus_id = vmbus_id
|
||||
d.class_id = class_id
|
||||
d.device_id = device_id
|
||||
d.dev_desc = dev_desc
|
||||
d.chn_vp_mapping = '\n'.join(chn_vp_mapping)
|
||||
if d.chn_vp_mapping:
|
||||
d.chn_vp_mapping += '\n'
|
||||
|
||||
vmbus_dev_list.append(d)
|
||||
|
||||
|
||||
vmbus_dev_list = sorted(vmbus_dev_list, key=lambda d: int(d.vmbus_id))
|
||||
|
||||
format0 = '%2s: %s'
|
||||
format1 = '%2s: Class_ID = %s - %s\n%s'
|
||||
format2 = '%2s: Class_ID = %s - %s\n\tDevice_ID = %s\n\tSysfs path: %s\n%s'
|
||||
|
||||
for d in vmbus_dev_list:
|
||||
if verbose == 0:
|
||||
print(('VMBUS ID ' + format0) % (d.vmbus_id, d.dev_desc))
|
||||
elif verbose == 1:
|
||||
print(
|
||||
('VMBUS ID ' + format1) %
|
||||
(d.vmbus_id, d.class_id, d.dev_desc, d.chn_vp_mapping)
|
||||
)
|
||||
else:
|
||||
print(
|
||||
('VMBUS ID ' + format2) %
|
||||
(
|
||||
d.vmbus_id, d.class_id, d.dev_desc,
|
||||
d.device_id, d.sysfs_path, d.chn_vp_mapping
|
||||
)
|
||||
)
|
@ -0,0 +1,318 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
/*
|
||||
* Copyright (c) 2009-2012,2016,2023 Microsoft Corp.
|
||||
* Copyright (c) 2012 NetApp Inc.
|
||||
* Copyright (c) 2012 Citrix Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <emmintrin.h>
|
||||
#include <linux/limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/uio.h>
|
||||
#include <unistd.h>
|
||||
#include "vmbus_bufring.h"
|
||||
|
||||
/**
|
||||
* Compiler barrier.
|
||||
*
|
||||
* Guarantees that operation reordering does not occur at compile time
|
||||
* for operations directly before and after the barrier.
|
||||
*/
|
||||
#define rte_compiler_barrier() ({ asm volatile ("" : : : "memory"); })
|
||||
|
||||
#define VMBUS_RQST_ERROR 0xFFFFFFFFFFFFFFFF
|
||||
#define ALIGN(val, align) ((typeof(val))((val) & (~((typeof(val))((align) - 1)))))
|
||||
|
||||
void *vmbus_uio_map(int *fd, int size)
|
||||
{
|
||||
void *map;
|
||||
|
||||
map = mmap(NULL, 2 * size, PROT_READ | PROT_WRITE, MAP_SHARED, *fd, 0);
|
||||
if (map == MAP_FAILED)
|
||||
return NULL;
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/* Increase bufring index by inc with wraparound */
|
||||
static inline uint32_t vmbus_br_idxinc(uint32_t idx, uint32_t inc, uint32_t sz)
|
||||
{
|
||||
idx += inc;
|
||||
if (idx >= sz)
|
||||
idx -= sz;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void vmbus_br_setup(struct vmbus_br *br, void *buf, unsigned int blen)
|
||||
{
|
||||
br->vbr = buf;
|
||||
br->windex = br->vbr->windex;
|
||||
br->dsize = blen - sizeof(struct vmbus_bufring);
|
||||
}
|
||||
|
||||
static inline __always_inline void
|
||||
rte_smp_mb(void)
|
||||
{
|
||||
asm volatile("lock addl $0, -128(%%rsp); " ::: "memory");
|
||||
}
|
||||
|
||||
static inline int
|
||||
rte_atomic32_cmpset(volatile uint32_t *dst, uint32_t exp, uint32_t src)
|
||||
{
|
||||
uint8_t res;
|
||||
|
||||
asm volatile("lock ; "
|
||||
"cmpxchgl %[src], %[dst];"
|
||||
"sete %[res];"
|
||||
: [res] "=a" (res), /* output */
|
||||
[dst] "=m" (*dst)
|
||||
: [src] "r" (src), /* input */
|
||||
"a" (exp),
|
||||
"m" (*dst)
|
||||
: "memory"); /* no-clobber list */
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
vmbus_txbr_copyto(const struct vmbus_br *tbr, uint32_t windex,
|
||||
const void *src0, uint32_t cplen)
|
||||
{
|
||||
uint8_t *br_data = tbr->vbr->data;
|
||||
uint32_t br_dsize = tbr->dsize;
|
||||
const uint8_t *src = src0;
|
||||
|
||||
/* XXX use double mapping like Linux kernel? */
|
||||
if (cplen > br_dsize - windex) {
|
||||
uint32_t fraglen = br_dsize - windex;
|
||||
|
||||
/* Wrap-around detected */
|
||||
memcpy(br_data + windex, src, fraglen);
|
||||
memcpy(br_data, src + fraglen, cplen - fraglen);
|
||||
} else {
|
||||
memcpy(br_data + windex, src, cplen);
|
||||
}
|
||||
|
||||
return vmbus_br_idxinc(windex, cplen, br_dsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write scattered channel packet to TX bufring.
|
||||
*
|
||||
* The offset of this channel packet is written as a 64bits value
|
||||
* immediately after this channel packet.
|
||||
*
|
||||
* The write goes through three stages:
|
||||
* 1. Reserve space in ring buffer for the new data.
|
||||
* Writer atomically moves priv_write_index.
|
||||
* 2. Copy the new data into the ring.
|
||||
* 3. Update the tail of the ring (visible to host) that indicates
|
||||
* next read location. Writer updates write_index
|
||||
*/
|
||||
static int
|
||||
vmbus_txbr_write(struct vmbus_br *tbr, const struct iovec iov[], int iovlen)
|
||||
{
|
||||
struct vmbus_bufring *vbr = tbr->vbr;
|
||||
uint32_t ring_size = tbr->dsize;
|
||||
uint32_t old_windex, next_windex, windex, total;
|
||||
uint64_t save_windex;
|
||||
int i;
|
||||
|
||||
total = 0;
|
||||
for (i = 0; i < iovlen; i++)
|
||||
total += iov[i].iov_len;
|
||||
total += sizeof(save_windex);
|
||||
|
||||
/* Reserve space in ring */
|
||||
do {
|
||||
uint32_t avail;
|
||||
|
||||
/* Get current free location */
|
||||
old_windex = tbr->windex;
|
||||
|
||||
/* Prevent compiler reordering this with calculation */
|
||||
rte_compiler_barrier();
|
||||
|
||||
avail = vmbus_br_availwrite(tbr, old_windex);
|
||||
|
||||
/* If not enough space in ring, then tell caller. */
|
||||
if (avail <= total)
|
||||
return -EAGAIN;
|
||||
|
||||
next_windex = vmbus_br_idxinc(old_windex, total, ring_size);
|
||||
|
||||
/* Atomic update of next write_index for other threads */
|
||||
} while (!rte_atomic32_cmpset(&tbr->windex, old_windex, next_windex));
|
||||
|
||||
/* Space from old..new is now reserved */
|
||||
windex = old_windex;
|
||||
for (i = 0; i < iovlen; i++)
|
||||
windex = vmbus_txbr_copyto(tbr, windex, iov[i].iov_base, iov[i].iov_len);
|
||||
|
||||
/* Set the offset of the current channel packet. */
|
||||
save_windex = ((uint64_t)old_windex) << 32;
|
||||
windex = vmbus_txbr_copyto(tbr, windex, &save_windex,
|
||||
sizeof(save_windex));
|
||||
|
||||
/* The region reserved should match region used */
|
||||
if (windex != next_windex)
|
||||
return -EINVAL;
|
||||
|
||||
/* Ensure that data is available before updating host index */
|
||||
rte_compiler_barrier();
|
||||
|
||||
/* Checkin for our reservation. wait for our turn to update host */
|
||||
while (!rte_atomic32_cmpset(&vbr->windex, old_windex, next_windex))
|
||||
_mm_pause();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rte_vmbus_chan_send(struct vmbus_br *txbr, uint16_t type, void *data,
|
||||
uint32_t dlen, uint32_t flags)
|
||||
{
|
||||
struct vmbus_chanpkt pkt;
|
||||
unsigned int pktlen, pad_pktlen;
|
||||
const uint32_t hlen = sizeof(pkt);
|
||||
uint64_t pad = 0;
|
||||
struct iovec iov[3];
|
||||
int error;
|
||||
|
||||
pktlen = hlen + dlen;
|
||||
pad_pktlen = ALIGN(pktlen, sizeof(uint64_t));
|
||||
|
||||
pkt.hdr.type = type;
|
||||
pkt.hdr.flags = flags;
|
||||
pkt.hdr.hlen = hlen >> VMBUS_CHANPKT_SIZE_SHIFT;
|
||||
pkt.hdr.tlen = pad_pktlen >> VMBUS_CHANPKT_SIZE_SHIFT;
|
||||
pkt.hdr.xactid = VMBUS_RQST_ERROR;
|
||||
|
||||
iov[0].iov_base = &pkt;
|
||||
iov[0].iov_len = hlen;
|
||||
iov[1].iov_base = data;
|
||||
iov[1].iov_len = dlen;
|
||||
iov[2].iov_base = &pad;
|
||||
iov[2].iov_len = pad_pktlen - pktlen;
|
||||
|
||||
error = vmbus_txbr_write(txbr, iov, 3);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
vmbus_rxbr_copyfrom(const struct vmbus_br *rbr, uint32_t rindex,
|
||||
void *dst0, size_t cplen)
|
||||
{
|
||||
const uint8_t *br_data = rbr->vbr->data;
|
||||
uint32_t br_dsize = rbr->dsize;
|
||||
uint8_t *dst = dst0;
|
||||
|
||||
if (cplen > br_dsize - rindex) {
|
||||
uint32_t fraglen = br_dsize - rindex;
|
||||
|
||||
/* Wrap-around detected. */
|
||||
memcpy(dst, br_data + rindex, fraglen);
|
||||
memcpy(dst + fraglen, br_data, cplen - fraglen);
|
||||
} else {
|
||||
memcpy(dst, br_data + rindex, cplen);
|
||||
}
|
||||
|
||||
return vmbus_br_idxinc(rindex, cplen, br_dsize);
|
||||
}
|
||||
|
||||
/* Copy data from receive ring but don't change index */
|
||||
static int
|
||||
vmbus_rxbr_peek(const struct vmbus_br *rbr, void *data, size_t dlen)
|
||||
{
|
||||
uint32_t avail;
|
||||
|
||||
/*
|
||||
* The requested data and the 64bits channel packet
|
||||
* offset should be there at least.
|
||||
*/
|
||||
avail = vmbus_br_availread(rbr);
|
||||
if (avail < dlen + sizeof(uint64_t))
|
||||
return -EAGAIN;
|
||||
|
||||
vmbus_rxbr_copyfrom(rbr, rbr->vbr->rindex, data, dlen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy data from receive ring and change index
|
||||
* NOTE:
|
||||
* We assume (dlen + skip) == sizeof(channel packet).
|
||||
*/
|
||||
static int
|
||||
vmbus_rxbr_read(struct vmbus_br *rbr, void *data, size_t dlen, size_t skip)
|
||||
{
|
||||
struct vmbus_bufring *vbr = rbr->vbr;
|
||||
uint32_t br_dsize = rbr->dsize;
|
||||
uint32_t rindex;
|
||||
|
||||
if (vmbus_br_availread(rbr) < dlen + skip + sizeof(uint64_t))
|
||||
return -EAGAIN;
|
||||
|
||||
/* Record where host was when we started read (for debug) */
|
||||
rbr->windex = rbr->vbr->windex;
|
||||
|
||||
/*
|
||||
* Copy channel packet from RX bufring.
|
||||
*/
|
||||
rindex = vmbus_br_idxinc(rbr->vbr->rindex, skip, br_dsize);
|
||||
rindex = vmbus_rxbr_copyfrom(rbr, rindex, data, dlen);
|
||||
|
||||
/*
|
||||
* Discard this channel packet's 64bits offset, which is useless to us.
|
||||
*/
|
||||
rindex = vmbus_br_idxinc(rindex, sizeof(uint64_t), br_dsize);
|
||||
|
||||
/* Update the read index _after_ the channel packet is fetched. */
|
||||
rte_compiler_barrier();
|
||||
|
||||
vbr->rindex = rindex;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rte_vmbus_chan_recv_raw(struct vmbus_br *rxbr,
|
||||
void *data, uint32_t *len)
|
||||
{
|
||||
struct vmbus_chanpkt_hdr pkt;
|
||||
uint32_t dlen, bufferlen = *len;
|
||||
int error;
|
||||
|
||||
error = vmbus_rxbr_peek(rxbr, &pkt, sizeof(pkt));
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (unlikely(pkt.hlen < VMBUS_CHANPKT_HLEN_MIN))
|
||||
/* XXX this channel is dead actually. */
|
||||
return -EIO;
|
||||
|
||||
if (unlikely(pkt.hlen > pkt.tlen))
|
||||
return -EIO;
|
||||
|
||||
/* Length are in quad words */
|
||||
dlen = pkt.tlen << VMBUS_CHANPKT_SIZE_SHIFT;
|
||||
*len = dlen;
|
||||
|
||||
/* If caller buffer is not large enough */
|
||||
if (unlikely(dlen > bufferlen))
|
||||
return -ENOBUFS;
|
||||
|
||||
/* Read data and skip packet header */
|
||||
error = vmbus_rxbr_read(rxbr, data, dlen, 0);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Return the number of bytes read */
|
||||
return dlen + sizeof(uint64_t);
|
||||
}
|
@ -0,0 +1,158 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
|
||||
#ifndef _VMBUS_BUF_H_
|
||||
#define _VMBUS_BUF_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define __packed __attribute__((__packed__))
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
#define ICMSGHDRFLAG_TRANSACTION 1
|
||||
#define ICMSGHDRFLAG_REQUEST 2
|
||||
#define ICMSGHDRFLAG_RESPONSE 4
|
||||
|
||||
#define IC_VERSION_NEGOTIATION_MAX_VER_COUNT 100
|
||||
#define ICMSG_HDR (sizeof(struct vmbuspipe_hdr) + sizeof(struct icmsg_hdr))
|
||||
#define ICMSG_NEGOTIATE_PKT_SIZE(icframe_vercnt, icmsg_vercnt) \
|
||||
(ICMSG_HDR + sizeof(struct icmsg_negotiate) + \
|
||||
(((icframe_vercnt) + (icmsg_vercnt)) * sizeof(struct ic_version)))
|
||||
|
||||
/*
|
||||
* Channel packets
|
||||
*/
|
||||
|
||||
/* Channel packet flags */
|
||||
#define VMBUS_CHANPKT_TYPE_INBAND 0x0006
|
||||
#define VMBUS_CHANPKT_TYPE_RXBUF 0x0007
|
||||
#define VMBUS_CHANPKT_TYPE_GPA 0x0009
|
||||
#define VMBUS_CHANPKT_TYPE_COMP 0x000b
|
||||
|
||||
#define VMBUS_CHANPKT_FLAG_NONE 0
|
||||
#define VMBUS_CHANPKT_FLAG_RC 0x0001 /* report completion */
|
||||
|
||||
#define VMBUS_CHANPKT_SIZE_SHIFT 3
|
||||
#define VMBUS_CHANPKT_SIZE_ALIGN BIT(VMBUS_CHANPKT_SIZE_SHIFT)
|
||||
#define VMBUS_CHANPKT_HLEN_MIN \
|
||||
(sizeof(struct vmbus_chanpkt_hdr) >> VMBUS_CHANPKT_SIZE_SHIFT)
|
||||
|
||||
/*
|
||||
* Buffer ring
|
||||
*/
|
||||
struct vmbus_bufring {
|
||||
volatile uint32_t windex;
|
||||
volatile uint32_t rindex;
|
||||
|
||||
/*
|
||||
* Interrupt mask {0,1}
|
||||
*
|
||||
* For TX bufring, host set this to 1, when it is processing
|
||||
* the TX bufring, so that we can safely skip the TX event
|
||||
* notification to host.
|
||||
*
|
||||
* For RX bufring, once this is set to 1 by us, host will not
|
||||
* further dispatch interrupts to us, even if there are data
|
||||
* pending on the RX bufring. This effectively disables the
|
||||
* interrupt of the channel to which this RX bufring is attached.
|
||||
*/
|
||||
volatile uint32_t imask;
|
||||
|
||||
/*
|
||||
* Win8 uses some of the reserved bits to implement
|
||||
* interrupt driven flow management. On the send side
|
||||
* we can request that the receiver interrupt the sender
|
||||
* when the ring transitions from being full to being able
|
||||
* to handle a message of size "pending_send_sz".
|
||||
*
|
||||
* Add necessary state for this enhancement.
|
||||
*/
|
||||
volatile uint32_t pending_send;
|
||||
uint32_t reserved1[12];
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint32_t feat_pending_send_sz:1;
|
||||
};
|
||||
uint32_t value;
|
||||
} feature_bits;
|
||||
|
||||
/* Pad it to rte_mem_page_size() so that data starts on page boundary */
|
||||
uint8_t reserved2[4028];
|
||||
|
||||
/*
|
||||
* Ring data starts here + RingDataStartOffset
|
||||
* !!! DO NOT place any fields below this !!!
|
||||
*/
|
||||
uint8_t data[];
|
||||
} __packed;
|
||||
|
||||
struct vmbus_br {
|
||||
struct vmbus_bufring *vbr;
|
||||
uint32_t dsize;
|
||||
uint32_t windex; /* next available location */
|
||||
};
|
||||
|
||||
struct vmbus_chanpkt_hdr {
|
||||
uint16_t type; /* VMBUS_CHANPKT_TYPE_ */
|
||||
uint16_t hlen; /* header len, in 8 bytes */
|
||||
uint16_t tlen; /* total len, in 8 bytes */
|
||||
uint16_t flags; /* VMBUS_CHANPKT_FLAG_ */
|
||||
uint64_t xactid;
|
||||
} __packed;
|
||||
|
||||
struct vmbus_chanpkt {
|
||||
struct vmbus_chanpkt_hdr hdr;
|
||||
} __packed;
|
||||
|
||||
struct vmbuspipe_hdr {
|
||||
unsigned int flags;
|
||||
unsigned int msgsize;
|
||||
} __packed;
|
||||
|
||||
struct ic_version {
|
||||
unsigned short major;
|
||||
unsigned short minor;
|
||||
} __packed;
|
||||
|
||||
struct icmsg_negotiate {
|
||||
unsigned short icframe_vercnt;
|
||||
unsigned short icmsg_vercnt;
|
||||
unsigned int reserved;
|
||||
struct ic_version icversion_data[]; /* any size array */
|
||||
} __packed;
|
||||
|
||||
struct icmsg_hdr {
|
||||
struct ic_version icverframe;
|
||||
unsigned short icmsgtype;
|
||||
struct ic_version icvermsg;
|
||||
unsigned short icmsgsize;
|
||||
unsigned int status;
|
||||
unsigned char ictransaction_id;
|
||||
unsigned char icflags;
|
||||
unsigned char reserved[2];
|
||||
} __packed;
|
||||
|
||||
int rte_vmbus_chan_recv_raw(struct vmbus_br *rxbr, void *data, uint32_t *len);
|
||||
int rte_vmbus_chan_send(struct vmbus_br *txbr, uint16_t type, void *data,
|
||||
uint32_t dlen, uint32_t flags);
|
||||
void vmbus_br_setup(struct vmbus_br *br, void *buf, unsigned int blen);
|
||||
void *vmbus_uio_map(int *fd, int size);
|
||||
|
||||
/* Amount of space available for write */
|
||||
static inline uint32_t vmbus_br_availwrite(const struct vmbus_br *br, uint32_t windex)
|
||||
{
|
||||
uint32_t rindex = br->vbr->rindex;
|
||||
|
||||
if (windex >= rindex)
|
||||
return br->dsize - (windex - rindex);
|
||||
else
|
||||
return rindex - windex;
|
||||
}
|
||||
|
||||
static inline uint32_t vmbus_br_availread(const struct vmbus_br *br)
|
||||
{
|
||||
return br->dsize - vmbus_br_availwrite(br, br->vbr->windex);
|
||||
}
|
||||
|
||||
#endif /* !_VMBUS_BUF_H_ */
|
@ -0,0 +1,499 @@
|
||||
# Hyper-V KVP daemon binary name
|
||||
%global hv_kvp_daemon hypervkvpd
|
||||
# Hyper-V VSS daemon binary name
|
||||
%global hv_vss_daemon hypervvssd
|
||||
# Hyper-V FCOPY daemon binary name
|
||||
%global hv_fcopy_uio_daemon hv_fcopy_uio_daemon
|
||||
# snapshot version
|
||||
%global snapver .20220731git
|
||||
# use hardened build
|
||||
%global _hardened_build 1
|
||||
# udev rules prefix
|
||||
%global udev_prefix 70
|
||||
|
||||
Name: hyperv-daemons
|
||||
Version: 0
|
||||
Release: 0.47%{?snapver}%{?dist}
|
||||
Summary: Hyper-V daemons suite
|
||||
|
||||
License: GPL-2.0-only
|
||||
URL: http://www.kernel.org
|
||||
|
||||
# Source files obtained from kernel upstream 4.17-rc1 (60cc43fc888428bb2f18f08997432d426a243338)
|
||||
# git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
|
||||
Source0: COPYING
|
||||
|
||||
# HYPERV KVP DAEMON
|
||||
Source1: hv_kvp_daemon.c
|
||||
Source2: hv_get_dhcp_info.sh
|
||||
Source3: hv_get_dns_info.sh
|
||||
Source4: hv_set_ifconfig.sh
|
||||
Source5: hypervkvpd.service
|
||||
Source6: hypervkvp.rules
|
||||
|
||||
# HYPERV VSS DAEMON
|
||||
Source100: hv_vss_daemon.c
|
||||
Source101: hypervvssd.service
|
||||
Source102: hypervvss.rules
|
||||
|
||||
# HYPERV FCOPY UIO DAEMON
|
||||
# source taken from https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/snapshot/linux-6.10-rc5.tar.gz
|
||||
Source200: hv_fcopy_uio_daemon.c
|
||||
Source201: hypervfcopyd.service
|
||||
Source202: vmbus_bufring.c
|
||||
Source203: vmbus_bufring.h
|
||||
# HYPERV TOOLS
|
||||
Source301: lsvmbus
|
||||
|
||||
# For RHEL-40107 - [Hyper-V][RHEL10] Request to update hypervkvpd related file /usr/libexec/hypervkvpd/hv_set_ifconfig same as RHEL 9.5 hv_set_ifconfig file.
|
||||
# For RHEL-40679 - [Hyper-V][RHEL10] Request to update hyperv-daemons vmbus_testing, hv_kvp_daemon.c, hv_vss_daemon.c files as same as RHEL 9.5
|
||||
Patch1: hpvd-Do-not-set-NM_CONTROLLED-no.patch
|
||||
# For RHEL-40107 - [Hyper-V][RHEL10] Request to update hypervkvpd related file /usr/libexec/hypervkvpd/hv_set_ifconfig same as RHEL 9.5 hv_set_ifconfig file.
|
||||
# For RHEL-40679 - [Hyper-V][RHEL10] Request to update hyperv-daemons vmbus_testing, hv_kvp_daemon.c, hv_vss_daemon.c files as same as RHEL 9.5
|
||||
Patch2: hpvd-Add-vmbus_testing-tool-build-files.patch
|
||||
# For RHEL-40107 - [Hyper-V][RHEL10] Request to update hypervkvpd related file /usr/libexec/hypervkvpd/hv_set_ifconfig same as RHEL 9.5 hv_set_ifconfig file.
|
||||
# For RHEL-40679 - [Hyper-V][RHEL10] Request to update hyperv-daemons vmbus_testing, hv_kvp_daemon.c, hv_vss_daemon.c files as same as RHEL 9.5
|
||||
Patch3: hpvd-hv_set_ifconfig.sh-Use-nmcli-commands.patch
|
||||
# For RHEL-40107 - [Hyper-V][RHEL10] Request to update hypervkvpd related file /usr/libexec/hypervkvpd/hv_set_ifconfig same as RHEL 9.5 hv_set_ifconfig file.
|
||||
# For RHEL-40679 - [Hyper-V][RHEL10] Request to update hyperv-daemons vmbus_testing, hv_kvp_daemon.c, hv_vss_daemon.c files as same as RHEL 9.5
|
||||
Patch4: hpvd-Use-filename-for-connection-profile.patch
|
||||
# For RHEL-40107 - [Hyper-V][RHEL10] Request to update hypervkvpd related file /usr/libexec/hypervkvpd/hv_set_ifconfig same as RHEL 9.5 hv_set_ifconfig file.
|
||||
# For RHEL-40679 - [Hyper-V][RHEL10] Request to update hyperv-daemons vmbus_testing, hv_kvp_daemon.c, hv_vss_daemon.c files as same as RHEL 9.5
|
||||
Patch5: hpvd-redhat-hv_set_if_config-Workaround-for-gateway-numbe.patch
|
||||
# For RHEL-40107 - [Hyper-V][RHEL10] Request to update hypervkvpd related file /usr/libexec/hypervkvpd/hv_set_ifconfig same as RHEL 9.5 hv_set_ifconfig file.
|
||||
# For RHEL-40679 - [Hyper-V][RHEL10] Request to update hyperv-daemons vmbus_testing, hv_kvp_daemon.c, hv_vss_daemon.c files as same as RHEL 9.5
|
||||
Patch6: hpvd-tools-hv-Remove-an-extraneous-the.patch
|
||||
# For RHEL-40107 - [Hyper-V][RHEL10] Request to update hypervkvpd related file /usr/libexec/hypervkvpd/hv_set_ifconfig same as RHEL 9.5 hv_set_ifconfig file.
|
||||
# For RHEL-40679 - [Hyper-V][RHEL10] Request to update hyperv-daemons vmbus_testing, hv_kvp_daemon.c, hv_vss_daemon.c files as same as RHEL 9.5
|
||||
Patch7: hpvd-tools-hv-kvp-remove-unnecessary-void-conversions.patch
|
||||
# For RHEL-40107 - [Hyper-V][RHEL10] Request to update hypervkvpd related file /usr/libexec/hypervkvpd/hv_set_ifconfig same as RHEL 9.5 hv_set_ifconfig file.
|
||||
# For RHEL-40679 - [Hyper-V][RHEL10] Request to update hyperv-daemons vmbus_testing, hv_kvp_daemon.c, hv_vss_daemon.c files as same as RHEL 9.5
|
||||
Patch8: hpvd-vmbus_testing-fix-wrong-python-syntax-for-integer-va.patch
|
||||
# For RHEL-40107 - [Hyper-V][RHEL10] Request to update hypervkvpd related file /usr/libexec/hypervkvpd/hv_set_ifconfig same as RHEL 9.5 hv_set_ifconfig file.
|
||||
# For RHEL-40679 - [Hyper-V][RHEL10] Request to update hyperv-daemons vmbus_testing, hv_kvp_daemon.c, hv_vss_daemon.c files as same as RHEL 9.5
|
||||
Patch9: hpvd-hv-hv_kvp_daemon-Support-for-keyfile-based-connectio.patch
|
||||
# For RHEL-40107 - [Hyper-V][RHEL10] Request to update hypervkvpd related file /usr/libexec/hypervkvpd/hv_set_ifconfig same as RHEL 9.5 hv_set_ifconfig file.
|
||||
# For RHEL-40679 - [Hyper-V][RHEL10] Request to update hyperv-daemons vmbus_testing, hv_kvp_daemon.c, hv_vss_daemon.c files as same as RHEL 9.5
|
||||
Patch10: hpvd-hv-hv_kvp_daemon-Some-small-fixes-for-handling-NM-ke.patch
|
||||
# For RHEL-40107 - [Hyper-V][RHEL10] Request to update hypervkvpd related file /usr/libexec/hypervkvpd/hv_set_ifconfig same as RHEL 9.5 hv_set_ifconfig file.
|
||||
# For RHEL-40679 - [Hyper-V][RHEL10] Request to update hyperv-daemons vmbus_testing, hv_kvp_daemon.c, hv_vss_daemon.c files as same as RHEL 9.5
|
||||
Patch11: hpvd-hv-hv_kvp_daemon-Handle-IPv4-and-Ipv6-combination-fo.patch
|
||||
# For RHEL-40107 - [Hyper-V][RHEL10] Request to update hypervkvpd related file /usr/libexec/hypervkvpd/hv_set_ifconfig same as RHEL 9.5 hv_set_ifconfig file.
|
||||
# For RHEL-40679 - [Hyper-V][RHEL10] Request to update hyperv-daemons vmbus_testing, hv_kvp_daemon.c, hv_vss_daemon.c files as same as RHEL 9.5
|
||||
Patch12: hpvd-Changes-for-adding-keyfile-support-in-RHEL-specific-.patch
|
||||
|
||||
# Hyper-V is available only on x86 and aarch64 architectures
|
||||
# The base empty (a.k.a. virtual) package can not be noarch
|
||||
# due to http://www.rpm.org/ticket/78
|
||||
ExclusiveArch: i686 x86_64 aarch64
|
||||
|
||||
Requires: hypervkvpd = %{version}-%{release}
|
||||
Requires: hypervvssd = %{version}-%{release}
|
||||
|
||||
# FCopy UIO driver does not seem to be supported on arm
|
||||
%ifnarch aarch64
|
||||
Requires: hypervfcopyd = %{version}-%{release}
|
||||
%else
|
||||
Obsoletes: hypervfcopyd <= %{version}-%{release}
|
||||
%endif
|
||||
BuildRequires: gcc
|
||||
|
||||
%description
|
||||
Suite of daemons that are needed when Linux guest
|
||||
is running on Windows Host with Hyper-V.
|
||||
|
||||
|
||||
%package -n hypervkvpd
|
||||
Summary: Hyper-V key value pair (KVP) daemon
|
||||
Requires: %{name}-license = %{version}-%{release}
|
||||
BuildRequires: systemd, kernel-headers
|
||||
Requires(post): systemd
|
||||
Requires(preun): systemd
|
||||
Requires(postun): systemd
|
||||
|
||||
%description -n hypervkvpd
|
||||
Hypervkvpd is an implementation of Hyper-V key value pair (KVP)
|
||||
functionality for Linux. The daemon first registers with the
|
||||
kernel driver. After this is done it collects information
|
||||
requested by Windows Host about the Linux Guest. It also supports
|
||||
IP injection functionality on the Guest.
|
||||
|
||||
|
||||
%package -n hypervvssd
|
||||
Summary: Hyper-V VSS daemon
|
||||
Requires: %{name}-license = %{version}-%{release}
|
||||
BuildRequires: systemd, kernel-headers
|
||||
Requires(post): systemd
|
||||
Requires(preun): systemd
|
||||
Requires(postun): systemd
|
||||
|
||||
%description -n hypervvssd
|
||||
Hypervvssd is an implementation of Hyper-V VSS functionality
|
||||
for Linux. The daemon is used for host initiated guest snapshot
|
||||
on Hyper-V hypervisor. The daemon first registers with the
|
||||
kernel driver. After this is done it waits for instructions
|
||||
from Windows Host if to "freeze" or "thaw" the filesystem
|
||||
on the Linux Guest.
|
||||
|
||||
%ifnarch aarch64
|
||||
# FCOPY UIO driver does not seem to be saupported on arm etc.
|
||||
%package -n hypervfcopyd
|
||||
Summary: Hyper-V FCOPY UIO daemon
|
||||
Requires: %{name}-license = %{version}-%{release}
|
||||
BuildRequires: systemd, kernel-headers
|
||||
Requires(post): systemd
|
||||
Requires(preun): systemd
|
||||
Requires(postun): systemd
|
||||
|
||||
%description -n hypervfcopyd
|
||||
Hypervfcopyd is an implementation of file copy service functionality
|
||||
for Linux Guest running on Hyper-V. The daemon enables host to copy
|
||||
a file (over VMBUS) into the Linux Guest. The daemon first registers
|
||||
with the kernel driver. After this is done it waits for instructions
|
||||
from Windows Host.
|
||||
%endif
|
||||
|
||||
%package license
|
||||
Summary: License of the Hyper-V daemons suite
|
||||
BuildArch: noarch
|
||||
|
||||
%description license
|
||||
Contains license of the Hyper-V daemons suite.
|
||||
|
||||
%package -n hyperv-tools
|
||||
Summary: Tools for Hyper-V guests
|
||||
BuildArch: noarch
|
||||
|
||||
%description -n hyperv-tools
|
||||
Contains tools and scripts useful for Hyper-V guests.
|
||||
|
||||
%prep
|
||||
%setup -Tc
|
||||
cp -pvL %{SOURCE0} COPYING
|
||||
|
||||
cp -pvL %{SOURCE1} hv_kvp_daemon.c
|
||||
cp -pvL %{SOURCE2} hv_get_dhcp_info.sh
|
||||
cp -pvL %{SOURCE3} hv_get_dns_info.sh
|
||||
cp -pvL %{SOURCE4} hv_set_ifconfig.sh
|
||||
cp -pvL %{SOURCE100} hv_vss_daemon.c
|
||||
|
||||
%ifnarch aarch64
|
||||
cp -pvL %{SOURCE200} hv_fcopy_uio_daemon.c
|
||||
cp -pvL %{SOURCE202} vmbus_bufring.c
|
||||
cp -pvL %{SOURCE203} vmbus_bufring.h
|
||||
%endif
|
||||
cp -pvL %{SOURCE301} lsvmbus
|
||||
|
||||
%autopatch -p1
|
||||
|
||||
%build
|
||||
# HYPERV KVP DAEMON
|
||||
%{__cc} $RPM_OPT_FLAGS -c hv_kvp_daemon.c
|
||||
%{__cc} $RPM_LD_FLAGS hv_kvp_daemon.o -o %{hv_kvp_daemon}
|
||||
|
||||
# HYPERV VSS DAEMON
|
||||
%{__cc} $RPM_OPT_FLAGS -c hv_vss_daemon.c
|
||||
%{__cc} $RPM_LD_FLAGS hv_vss_daemon.o -o %{hv_vss_daemon}
|
||||
|
||||
|
||||
%ifnarch aarch64
|
||||
# HYPERV FCOPY UIO DAEMON
|
||||
%{__cc} $RPM_OPT_FLAGS -c hv_fcopy_uio_daemon.c
|
||||
%{__cc} $RPM_OPT_FLAGS -c vmbus_bufring.c
|
||||
%{__cc} $RPM_LD_FLAGS vmbus_bufring.o hv_fcopy_uio_daemon.o -o %{hv_fcopy_uio_daemon}
|
||||
%endif
|
||||
|
||||
%install
|
||||
rm -rf %{buildroot}
|
||||
|
||||
mkdir -p %{buildroot}%{_sbindir}
|
||||
install -p -m 0755 %{hv_kvp_daemon} %{buildroot}%{_sbindir}
|
||||
install -p -m 0755 %{hv_vss_daemon} %{buildroot}%{_sbindir}
|
||||
|
||||
%ifnarch aarch64
|
||||
install -p -m 0755 %{hv_fcopy_uio_daemon} %{buildroot}%{_sbindir}
|
||||
%endif
|
||||
|
||||
# Systemd unit file
|
||||
mkdir -p %{buildroot}%{_unitdir}
|
||||
install -p -m 0644 %{SOURCE5} %{buildroot}%{_unitdir}
|
||||
install -p -m 0644 %{SOURCE101} %{buildroot}%{_unitdir}
|
||||
%ifnarch aarch64
|
||||
install -p -m 0644 %{SOURCE201} %{buildroot}%{_unitdir}
|
||||
%endif
|
||||
# Udev rules
|
||||
mkdir -p %{buildroot}%{_udevrulesdir}
|
||||
install -p -m 0644 %{SOURCE6} %{buildroot}%{_udevrulesdir}/%{udev_prefix}-hypervkvp.rules
|
||||
install -p -m 0644 %{SOURCE102} %{buildroot}%{_udevrulesdir}/%{udev_prefix}-hypervvss.rules
|
||||
# Shell scripts for the KVP daemon
|
||||
mkdir -p %{buildroot}%{_libexecdir}/%{hv_kvp_daemon}
|
||||
install -p -m 0755 hv_get_dhcp_info.sh %{buildroot}%{_libexecdir}/%{hv_kvp_daemon}/hv_get_dhcp_info
|
||||
install -p -m 0755 hv_get_dns_info.sh %{buildroot}%{_libexecdir}/%{hv_kvp_daemon}/hv_get_dns_info
|
||||
install -p -m 0755 hv_set_ifconfig.sh %{buildroot}%{_libexecdir}/%{hv_kvp_daemon}/hv_set_ifconfig
|
||||
# Directory for pool files
|
||||
mkdir -p %{buildroot}%{_sharedstatedir}/hyperv
|
||||
|
||||
# Tools
|
||||
install -p -m 0755 lsvmbus %{buildroot}%{_sbindir}/
|
||||
sed -i 's,#!/usr/bin/env python,#!/usr/bin/python3,' %{buildroot}%{_sbindir}/lsvmbus
|
||||
install -p -m 0755 vmbus_testing %{buildroot}%{_sbindir}/
|
||||
|
||||
%post -n hypervkvpd
|
||||
if [ $1 -gt 1 ] ; then
|
||||
# Upgrade
|
||||
systemctl --no-reload disable hypervkvpd.service >/dev/null 2>&1 || :
|
||||
fi
|
||||
|
||||
%preun -n hypervkvpd
|
||||
%systemd_preun hypervkvpd.service
|
||||
|
||||
%postun -n hypervkvpd
|
||||
# hypervkvpd daemon does NOT support restarting (driver, neither)
|
||||
%systemd_postun hypervkvpd.service
|
||||
# If removing the package, delete %%{_sharedstatedir}/hyperv directory
|
||||
if [ "$1" -eq "0" ] ; then
|
||||
rm -rf %{_sharedstatedir}/hyperv || :
|
||||
fi
|
||||
|
||||
|
||||
%post -n hypervvssd
|
||||
if [ $1 -gt 1 ] ; then
|
||||
# Upgrade
|
||||
systemctl --no-reload disable hypervvssd.service >/dev/null 2>&1 || :
|
||||
fi
|
||||
|
||||
%postun -n hypervvssd
|
||||
%systemd_postun hypervvssd.service
|
||||
|
||||
%preun -n hypervvssd
|
||||
%systemd_preun hypervvssd.service
|
||||
|
||||
%ifnarch aarch64
|
||||
%post -n hypervfcopyd
|
||||
if [ $1 -gt 1 ] ; then
|
||||
# Upgrade
|
||||
systemctl --no-reload disable hypervfcopyd.service >/dev/null 2>&1 || :
|
||||
fi
|
||||
|
||||
%postun -n hypervfcopyd
|
||||
%systemd_postun hypervfcopyd.service
|
||||
|
||||
%preun -n hypervfcopyd
|
||||
%systemd_preun hypervfcopyd.service
|
||||
%endif
|
||||
|
||||
%files
|
||||
# the base package does not contain any files.
|
||||
|
||||
%files -n hypervkvpd
|
||||
%{_sbindir}/%{hv_kvp_daemon}
|
||||
%{_unitdir}/hypervkvpd.service
|
||||
%{_udevrulesdir}/%{udev_prefix}-hypervkvp.rules
|
||||
%dir %{_libexecdir}/%{hv_kvp_daemon}
|
||||
%{_libexecdir}/%{hv_kvp_daemon}/*
|
||||
%dir %{_sharedstatedir}/hyperv
|
||||
|
||||
%files -n hypervvssd
|
||||
%{_sbindir}/%{hv_vss_daemon}
|
||||
%{_unitdir}/hypervvssd.service
|
||||
%{_udevrulesdir}/%{udev_prefix}-hypervvss.rules
|
||||
|
||||
%ifnarch aarch64
|
||||
%files -n hypervfcopyd
|
||||
%{_sbindir}/%{hv_fcopy_uio_daemon}
|
||||
%{_unitdir}/hypervfcopyd.service
|
||||
%endif
|
||||
|
||||
%files license
|
||||
%doc COPYING
|
||||
|
||||
%files -n hyperv-tools
|
||||
%{_sbindir}/lsvmbus
|
||||
%{_sbindir}/vmbus_testing
|
||||
|
||||
%changelog
|
||||
* Tue Nov 26 2024 MSVSphere Packaging Team <packager@msvsphere-os.ru> - 0-0.47.20220731git
|
||||
- Rebuilt for MSVSphere 10
|
||||
|
||||
* Fri Jul 12 2024 Miroslav Rezanina <mrezanin@redhat.com> - 0-0.47.20220731git
|
||||
- hpvd-Add-support-for-newer-fcopy-UIO-hyperv-daemons-modul.patch [RHEL-44617]
|
||||
- hpvd-Update-main-package-dep-on-hypervfcopyd-to-be-arch-d.patch [RHEL-44617]
|
||||
- hpvd-Particularize-hypervfcopyd-service-requirements.patch [RHEL-44617]
|
||||
- Resolves: RHEL-44617
|
||||
([RHEL-10] Add support for fcopy UIO userland module in hyperv-daemons)
|
||||
|
||||
* Thu Jun 27 2024 Miroslav Rezanina <mrezanin@redhat.com> - 0-0.46.20220731git
|
||||
- hpvd-Add-support-for-patching-hyperv-daemons.patch [RHEL-40107 RHEL-40679]
|
||||
- hpvd-Do-not-set-NM_CONTROLLED-no.patch [RHEL-40107 RHEL-40679]
|
||||
- hpvd-Add-vmbus_testing-tool-build-files.patch [RHEL-40107 RHEL-40679]
|
||||
- hpvd-hv_set_ifconfig.sh-Use-nmcli-commands.patch [RHEL-40107 RHEL-40679]
|
||||
- hpvd-Use-filename-for-connection-profile.patch [RHEL-40107 RHEL-40679]
|
||||
- hpvd-redhat-hv_set_if_config-Workaround-for-gateway-numbe.patch [RHEL-40107 RHEL-40679]
|
||||
- hpvd-tools-hv-Remove-an-extraneous-the.patch [RHEL-40107 RHEL-40679]
|
||||
- hpvd-tools-hv-kvp-remove-unnecessary-void-conversions.patch [RHEL-40107 RHEL-40679]
|
||||
- hpvd-vmbus_testing-fix-wrong-python-syntax-for-integer-va.patch [RHEL-40107 RHEL-40679]
|
||||
- hpvd-hv-hv_kvp_daemon-Support-for-keyfile-based-connectio.patch [RHEL-40107 RHEL-40679]
|
||||
- hpvd-hv-hv_kvp_daemon-Some-small-fixes-for-handling-NM-ke.patch [RHEL-40107 RHEL-40679]
|
||||
- hpvd-hv-hv_kvp_daemon-Handle-IPv4-and-Ipv6-combination-fo.patch [RHEL-40107 RHEL-40679]
|
||||
- hpvd-Changes-for-adding-keyfile-support-in-RHEL-specific-.patch [RHEL-40107 RHEL-40679]
|
||||
- hpvd-Remove-hyperv_fcopy_daemon-as-the-c10s-kernel-does-n.patch [RHEL-40107 RHEL-40679]
|
||||
- Resolves: RHEL-40107
|
||||
([Hyper-V][RHEL10] Request to update hypervkvpd related file /usr/libexec/hypervkvpd/hv_set_ifconfig same as RHEL 9.5 hv_set_ifconfig file.)
|
||||
- Resolves: RHEL-40679
|
||||
([Hyper-V][RHEL10] Request to update hyperv-daemons vmbus_testing, hv_kvp_daemon.c, hv_vss_daemon.c files as same as RHEL 9.5)
|
||||
|
||||
* Mon Jun 24 2024 Troy Dawson <tdawson@redhat.com> - 0-0.45.20220731git
|
||||
- Bump release for June 2024 mass rebuild
|
||||
|
||||
* Wed Jan 24 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.44.20220731git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
|
||||
|
||||
* Sat Jan 20 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.43.20220731git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
|
||||
|
||||
* Thu Jul 20 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.42.20220731git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
|
||||
|
||||
* Tue May 30 2023 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.41.20220731git
|
||||
- Switch to SPDX identifiers for the license field
|
||||
|
||||
* Thu Jan 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.40.20220731git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
|
||||
|
||||
* Tue Aug 02 2022 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.39.20220731git
|
||||
- Enable aarch64 build (#2111394)
|
||||
- Fix typos in shell scripts
|
||||
|
||||
* Thu Jul 21 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.38.20220710git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
|
||||
|
||||
* Thu Jul 14 2022 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.37.20220710git
|
||||
- Update to 5.19-rc6
|
||||
|
||||
* Fri Jul 01 2022 Chris Patterson <cpatterson@microsoft.com> - 0-0.37.20190303git
|
||||
- Only start kvpd under Hyper-V
|
||||
- Minimize dependencies for kvpd to ensure it starts before cloud-init
|
||||
|
||||
* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.36.20190303git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
|
||||
|
||||
* Thu Jul 22 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.35.20190303git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
|
||||
|
||||
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.34.20190303git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
|
||||
|
||||
* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.33.20190303git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
|
||||
|
||||
* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.32.20190303git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
|
||||
|
||||
* Wed Jan 15 2020 Tom Stellard <tstellar@redhat.com> - 0-0.31.20190303git
|
||||
- Use __cc macro instead of hard-coding gcc
|
||||
|
||||
* Fri Nov 08 2019 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.30.20190303git
|
||||
- Rebase to 5.4-rc6
|
||||
- Add IgnoreOnIsolate to systemd units
|
||||
|
||||
* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.29.20190303git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
|
||||
|
||||
* Fri Mar 15 2019 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.28.20190303git
|
||||
- Rebase to 5.0
|
||||
|
||||
* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.27.20180415git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
|
||||
|
||||
* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.26.20180415git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
|
||||
|
||||
* Mon Jun 11 2018 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.25.20180415git
|
||||
- Switch lsvmbus to Python3
|
||||
|
||||
* Thu Apr 26 2018 Tomas Hozza <thozza@redhat.com> - 0-0.24.20180415git
|
||||
- Added gcc as an explicit BuildRequires
|
||||
|
||||
* Thu Apr 19 2018 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.23.20180415git
|
||||
- Rebase to 4.17-rc1
|
||||
|
||||
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.22.20170105git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
|
||||
|
||||
* Mon Dec 11 2017 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.21.20170105git
|
||||
- Rebase to 4.15-rc2, drop fedora patches as changes are upstream
|
||||
- Start kvpd after network.target
|
||||
|
||||
* Wed Aug 02 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.20.20170105git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
|
||||
|
||||
* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.19.20170105git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
|
||||
|
||||
* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.18.20170105git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
|
||||
|
||||
* Wed Jan 11 2017 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.17.20160728git
|
||||
- Use '-gt' instead of '>' to do the right comparison (#1412033)
|
||||
|
||||
* Thu Jan 05 2017 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.16.20160728git
|
||||
- Rebase to 4.9
|
||||
- hyperv-tools subpackage added
|
||||
|
||||
* Thu Jul 28 2016 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.15.20160728git
|
||||
- Rebase to 4.8-rc0 (20160728 git snapshot)
|
||||
- Disable services and remove ConditionVirtualization, multi-user.target
|
||||
dependencies switching to udev-only activation (#1331577)
|
||||
|
||||
* Thu Feb 04 2016 Fedora Release Engineering <releng@fedoraproject.org> - 0-0.14.20150702git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
|
||||
|
||||
* Wed Nov 18 2015 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.13.20150702git
|
||||
- Add udev rules to properly restart services (#1195029)
|
||||
- Spec cleanup
|
||||
|
||||
* Thu Jul 02 2015 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.12.20150702git
|
||||
- Rebase to 4.2-rc0 (20150702 git snapshot)
|
||||
- Switch to new chardev-based communication layer (#1195029)
|
||||
|
||||
* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0-0.11.20150108git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
|
||||
|
||||
* Thu Jan 08 2015 Vitaly Kuznetsov <vkuznets@redhat.com> - 0-0.10.20150108git
|
||||
- Rebase to 3.19-rc3 (20150108 git snapshot)
|
||||
- Drop 'nodaemon' patches, use newly introduced '-n' option
|
||||
|
||||
* Sat Aug 16 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0-0.9.20140714git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
|
||||
|
||||
* Mon Jul 14 2014 Tomas Hozza <thozza@redhat.com> - 0-0.8.20140714git
|
||||
- Update the File copy daemon to the latest git snapshot
|
||||
- Fix hyperfcopyd.service to check for /dev/vmbus/hv_fcopy
|
||||
|
||||
* Wed Jun 11 2014 Tomas Hozza <thozza@redhat.com> - 0-0.7.20140611git
|
||||
- Fix FTBFS (#1106781)
|
||||
- Use kernel-headers instead of kernel-devel for building
|
||||
- package new Hyper-V fcopy daemon as hypervfcopyd sub-package
|
||||
|
||||
* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0-0.6.20140219git
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
|
||||
|
||||
* Wed Feb 19 2014 Tomas Hozza <thozza@redhat.com> - 0-0.5.20140219git
|
||||
- rebase to the latest git snapshot next-20140219
|
||||
- KVP, VSS: removed inclusion of linux/types.h
|
||||
- VSS: Ignore VFAT mounts during freeze operation
|
||||
|
||||
* Fri Jan 10 2014 Tomas Hozza <thozza@redhat.com> - 0-0.4.20131022git
|
||||
- provide 'hyperv-daemons' package for convenient installation of all daemons
|
||||
|
||||
* Tue Oct 22 2013 Tomas Hozza <thozza@redhat.com> - 0-0.3.20131022git
|
||||
- rebase to the latest git snapshot next-20130927 (obtained 2013-10-22)
|
||||
- KVP, VSS: daemon use single buffer for send/recv
|
||||
- KVP: FQDN is obtained on start and cached
|
||||
|
||||
* Fri Sep 20 2013 Tomas Hozza <thozza@redhat.com> - 0-0.2.20130826git
|
||||
- Use 'hypervkvpd' directory in libexec for KVP daemon scripts (#1010268)
|
||||
- daemons are now WantedBy multi-user.target instead of basic.target (#1010260)
|
||||
|
||||
* Mon Aug 26 2013 Tomas Hozza <thozza@redhat.com> - 0-0.1.20130826git
|
||||
- Initial package
|
Loading…
Reference in new issue