Refactor ss service

Signed-off-by: Ze Gan <ganze718@gmail.com>
This commit is contained in:
Ze Gan 2024-02-26 00:58:22 +08:00
parent 8b163b1ccf
commit e6bc0f3b5d
17 changed files with 392 additions and 136 deletions

View File

@ -47,6 +47,7 @@ DOCKER_CTL_SCRIPT="$DOCKER_CTL_DIR/docker.sh"
FILESYSTEM_ROOT_USR="$FILESYSTEM_ROOT/usr"
FILESYSTEM_ROOT_USR_LIB="$FILESYSTEM_ROOT/usr/lib/"
FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM="$FILESYSTEM_ROOT_USR_LIB/systemd/system"
FILESYSTEM_ROOT_USR_LIB_SYSTEMD_NETWORK="$FILESYSTEM_ROOT_USR_LIB/systemd/network"
FILESYSTEM_ROOT_USR_SHARE="$FILESYSTEM_ROOT_USR/share"
FILESYSTEM_ROOT_USR_SHARE_SONIC="$FILESYSTEM_ROOT_USR_SHARE/sonic"
FILESYSTEM_ROOT_USR_SHARE_SONIC_SCRIPTS="$FILESYSTEM_ROOT_USR_SHARE_SONIC/scripts"
@ -629,6 +630,25 @@ sudo cp $IMAGE_CONFIGS/config-chassisdb/config-chassisdb $FILESYSTEM_ROOT/usr/bi
echo "config-chassisdb.service" | sudo tee -a $GENERATED_SERVICE_FILE
sudo LANG=C chroot $FILESYSTEM_ROOT systemctl enable config-chassisdb.service
# Copy midplane network service file for smart switch
sudo cp $IMAGE_CONFIGS/midplane-network/bridge-midplane.netdev $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_NETWORK/bridge-midplane.netdev
sudo cp $IMAGE_CONFIGS/midplane-network/bridge-midplane.network $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_NETWORK/bridge-midplane.network
sudo cp $IMAGE_CONFIGS/midplane-network/midplane-network-npu.network $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_NETWORK/midplane-network-npu.network
sudo cp $IMAGE_CONFIGS/midplane-network/midplane-network-dpu.network $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_NETWORK/midplane-network-dpu.network
sudo cp $IMAGE_CONFIGS/midplane-network/midplane-network-npu.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM/midplane-network-npu.service
sudo cp $IMAGE_CONFIGS/midplane-network/midplane-network-dpu.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM/midplane-network-dpu.service
# Disable smart switch unit by default, these units will be controlled by systemd-sonic-generator
sudo ln -s /dev/null /etc/systemd/network/bridge-midplane.netdev
sudo ln -s /dev/null /etc/systemd/network/bridge-midplane.network
sudo ln -s /dev/null /etc/systemd/network/midplane-network-npu.network
sudo ln -s /dev/null /etc/systemd/network/midplane-network-dpu.network
echo "midplane-network-npu.service" | sudo tee -a $GENERATED_SERVICE_FILE
sudo LANG=C chroot $FILESYSTEM_ROOT systemctl disable midplane-network-npu.service
echo "midplane-network-dpu.service" | sudo tee -a $GENERATED_SERVICE_FILE
sudo LANG=C chroot $FILESYSTEM_ROOT systemctl disable midplane-network-dpu.service
# Copy backend-acl script and service file
sudo cp $IMAGE_CONFIGS/backend_acl/backend-acl.service $FILESYSTEM_ROOT_USR_LIB_SYSTEMD_SYSTEM/backend-acl.service
sudo cp $IMAGE_CONFIGS/backend_acl/backend_acl.py $FILESYSTEM_ROOT/usr/bin/backend_acl.py

View File

@ -0,0 +1,5 @@
# Bridge interface for midplane network
[NetDev]
Name=bridge-midplane
Kind=bridge

View File

@ -0,0 +1,7 @@
# Midplane network for NPU
[Match]
Name=bridge-midplane
[Network]
Address=169.254.200.254/24

View File

@ -0,0 +1,5 @@
[Match]
Name=eth0-midplane
[Network]
DHCP=yes

View File

@ -0,0 +1,15 @@
# Oneshot midplane network service
[Unit]
Description=Midplane network service
Requires=systemd-networkd.service
After=systemd-networkd.service
Before=database.service
[Service]
Type=oneshot
User=root
ExecStart=/usr/lib/systemd/systemd-networkd-wait-online -i eth0-midplane --timeout=600
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,5 @@
[Match]
Name=dpu*
[Network]
Bridge=bridge-midplane

View File

@ -0,0 +1,14 @@
# Oneshot midplane network service
[Unit]
Description=Midplane network service
Requires=systemd-networkd.service
After=systemd-networkd.service
[Service]
Type=oneshot
User=root
ExecStart=/usr/lib/systemd/systemd-networkd-wait-online -i bridge-midplane
[Install]
WantedBy=multi-user.target

View File

@ -9,6 +9,7 @@
#include <mutex>
#include <string>
#include <sys/stat.h>
#include <linux/limits.h>
#include <gtest/gtest.h>
#include <boost/filesystem.hpp>
#include <boost/format.hpp>
@ -41,6 +42,7 @@ namespace SSGTest {
*/
const std::string TEST_ROOT_DIR = "tests/ssg-test/";
const std::string TEST_UNIT_FILE_PREFIX = TEST_ROOT_DIR + "systemd/";
const std::string TEST_LIB_NETWORK = TEST_UNIT_FILE_PREFIX + "network/";
const std::string TEST_ASIC_CONF_FORMAT = TEST_ROOT_DIR + "%s/asic.conf";
const std::string TEST_PLATFORM_CONF_FORMAT = TEST_ROOT_DIR + "%s/platform.json";
const std::string TEST_MACHINE_CONF = TEST_ROOT_DIR + "machine.conf";
@ -50,23 +52,26 @@ const std::string TEST_ASIC_CONF = TEST_PLATFORM_DIR + "asic.conf";
const std::string TEST_PLATFORM_CONF = TEST_PLATFORM_DIR + "platform.json";
const std::string TEST_OUTPUT_DIR = TEST_ROOT_DIR + "generator/";
const std::string TEST_ETC_NETWORK = TEST_OUTPUT_DIR + "network/";
const std::string TEST_CONFIG_FILE = TEST_ROOT_DIR + "generated_services.conf";
const std::string TEST_UNIT_FILES = "tests/testfiles/";
/* Input data for generated_services.conf */
const std::vector<std::string> generated_services = {
"multi_inst_a.service", /* Single instance of a multi asic service a */
"multi_inst_a@.service", /* Multi-instance of a multi asic service a */
"multi_inst_b@.service", /* Multi-instance of a multi asic service b */
"single_inst.service", /* A single instance service */
"test.service", /* A single instance test service
to test dependency creation */
"test.timer", /* A timer service */
"midplane-network.service", /* A midplane network service for smart switch*/
"database.service", /* A database service*/
"database@.service", /* A database service for multi instances */
"multi_inst_a.service", /* Single instance of a multi asic service a */
"multi_inst_a@.service", /* Multi-instance of a multi asic service a */
"multi_inst_b@.service", /* Multi-instance of a multi asic service b */
"single_inst.service", /* A single instance service */
"test.service", /* A single instance test service
to test dependency creation */
"test.timer", /* A timer service */
"midplane-network-npu.service", /* A midplane network service for smart switch NPU*/
"midplane-network-dpu.service", /* A midplane network service for smart switch DPU*/
"database.service", /* A database service*/
"database@.service", /* A database service for multi instances */
};
static std::mutex g_ssg_test_mutex;
@ -126,8 +131,13 @@ class SsgFunctionTest : public SystemdSonicGeneratorFixture {
try {
fs::path current(file->path());
if(!fs::is_directory(current)) {
std::string ext = boost::filesystem::extension(current);
fs::path dest_path = dest_dir;
if (ext == ".netdev" || ext == ".network" || ext == ".link") {
dest_path = dest_path / "network";
}
/* Copy file */
fs::copy_file( current, dest_dir / current.filename());
fs::copy_file( current, dest_path / current.filename());
}
}
catch(fs::filesystem_error const & e) {
@ -148,6 +158,10 @@ class SsgFunctionTest : public SystemdSonicGeneratorFixture {
fs::create_directories(path);
path = fs::path(TEST_PLATFORM_DIR.c_str());
fs::create_directories(path);
path = fs::path(TEST_LIB_NETWORK.c_str());
fs::create_directories(path);
path = fs::path(TEST_ETC_NETWORK.c_str());
fs::create_directories(path);
fp = fopen(TEST_MACHINE_CONF.c_str(), "w");
ASSERT_NE(fp, nullptr);
fputs("onie_platform=test_platform", fp);
@ -262,7 +276,10 @@ class SsgMainTest : public SsgFunctionTest {
finished = true;
}
fs::path path{TEST_OUTPUT_DIR + target + "/" + str_t};
EXPECT_EQ(fs::exists(path), expected_result)
char resolved_path[PATH_MAX];
realpath(path.c_str(), resolved_path);
bool exist = fs::exists(path) && strcmp(resolved_path, "/dev/null") != 0;
EXPECT_EQ(exist, expected_result)
<< "Failed validation: " << path;
}
}
@ -293,7 +310,8 @@ class SsgMainTest : public SsgFunctionTest {
*/
validate_output_dependency_list(single_asic_dependency_list_split,
test_service, IS_SINGLE_ASIC(cfg.num_asics), cfg.num_asics);
validate_output_dependency_list(npu_dependency_list,
"midplane-network-npu.service", true, cfg.num_dpus);
} else {
/* Validate Unit file dependency creation for single instance
* services. These entries should not be present for multi asic
@ -309,15 +327,6 @@ class SsgMainTest : public SsgFunctionTest {
*/
validate_output_dependency_list(common_dependency_list,
test_service, true, cfg.num_asics);
/* Validate Unit file dependency creation for smart switch
* services. These entries should not be present for npu
* and dpu of smart switch.
*/
validate_output_dependency_list(smart_switch_dependency_list,
"database.service", cfg.is_smart_switch_dpu || cfg.is_smart_switch_npu, cfg.num_asics);
validate_output_dependency_list(smart_switch_dependency_list,
"database@.service", cfg.is_smart_switch_npu, cfg.num_asics);
}
/*
@ -331,8 +340,14 @@ class SsgMainTest : public SsgFunctionTest {
test_target, IS_SINGLE_ASIC(cfg.num_asics), cfg.num_asics);
validate_output_unit_files(common_service_list,
test_target, true, cfg.num_asics);
validate_output_unit_files(smart_switch_service_list,
test_target, cfg.is_smart_switch_dpu || cfg.is_smart_switch_npu, cfg.num_dpus);
validate_output_unit_files(npu_service_list,
test_target, cfg.is_smart_switch_npu, cfg.num_dpus);
validate_output_unit_files(npu_network_service_list,
"network", cfg.is_smart_switch_npu, cfg.num_dpus);
validate_output_unit_files(dpu_service_list,
test_target, cfg.is_smart_switch_dpu, cfg.num_dpus);
validate_output_unit_files(dpu_network_service_list,
"network", cfg.is_smart_switch_dpu, cfg.num_dpus);
}
/* ssg_main test routine.
@ -353,6 +368,11 @@ class SsgMainTest : public SsgFunctionTest {
g_machine_config_file = TEST_MACHINE_CONF.c_str();
g_asic_conf_format = TEST_ASIC_CONF_FORMAT.c_str();
g_platform_file_format = TEST_PLATFORM_CONF_FORMAT.c_str();
std::string lib_systemd = fs::current_path().string() + "/" + TEST_UNIT_FILE_PREFIX;
g_lib_systemd = lib_systemd.c_str();
std::string etc_systemd = fs::current_path().string() + "/" + TEST_OUTPUT_DIR;
g_etc_systemd = etc_systemd.c_str();
/* Set NUM_ASIC value in asic.conf */
fp = fopen(TEST_ASIC_CONF.c_str(), "w");
@ -402,6 +422,13 @@ class SsgMainTest : public SsgFunctionTest {
/* Save global variables before running tests */
virtual void SetUp() {
SsgFunctionTest::SetUp();
// Create /dev/null symlink for simulation disabled service
std::vector<std::string> disabled_service;
disabled_service.insert(disabled_service.end(), npu_network_service_list.begin(), npu_network_service_list.end());
disabled_service.insert(disabled_service.end(), dpu_network_service_list.begin(), dpu_network_service_list.end());
for (const auto &service : disabled_service) {
fs::create_symlink("/dev/null", TEST_ETC_NETWORK + service);
}
}
/* Restore global vars */
@ -414,12 +441,15 @@ class SsgMainTest : public SsgFunctionTest {
static const std::vector<std::string> single_asic_service_list;
static const std::vector<std::string> multi_asic_service_list;
static const std::vector<std::string> common_service_list;
static const std::vector<std::string> smart_switch_service_list;
static const std::vector<std::string> npu_service_list;
static const std::vector<std::string> npu_network_service_list;
static const std::vector<std::string> dpu_service_list;
static const std::vector<std::string> dpu_network_service_list;
static const std::vector<std::string> single_asic_dependency_list;
static const std::vector<std::string> single_asic_dependency_list_split;
static const std::vector<std::string> multi_asic_dependency_list;
static const std::vector<std::string> npu_dependency_list;
static const std::vector<std::string> common_dependency_list;
static const std::vector<std::string> smart_switch_dependency_list;
};
/*
@ -454,11 +484,31 @@ SsgMainTest::common_service_list = {
"database.service",
};
/* Common Systemd service Unit file list for single and multi asic system. */
/* Systemd service Unit file list for Smart Switch NPU. */
const std::vector<std::string>
SsgMainTest::smart_switch_service_list = {
SsgMainTest::npu_service_list = {
"database@dpu%1%.service",
"midplane-network.service",
"midplane-network-npu.service",
};
/* Systemd service Unit file list for Smart Switch NPU. */
const std::vector<std::string>
SsgMainTest::npu_network_service_list = {
"bridge-midplane.netdev",
"bridge-midplane.network",
"midplane-network-npu.network",
};
/* Systemd service Unit file list for Smart Switch DPU. */
const std::vector<std::string>
SsgMainTest::dpu_service_list = {
"midplane-network-dpu.service",
};
/* Systemd service Unit file list for Smart Switch DPU. */
const std::vector<std::string>
SsgMainTest::dpu_network_service_list = {
"midplane-network-dpu.network",
};
/*
@ -503,9 +553,8 @@ SsgMainTest::common_dependency_list = {
};
const std::vector<std::string>
SsgMainTest::smart_switch_dependency_list = {
"Requires=midplane-network.service",
"After=midplane-network.service",
SsgMainTest::npu_dependency_list = {
"Before=database@dpu%1%.service",
};
/* Test get functions for global vasr*/
@ -590,15 +639,22 @@ TEST_F(SsgFunctionTest, get_num_of_asic) {
/* TEST get_unit_files()*/
TEST_F(SsgFunctionTest, get_unit_files) {
g_unit_file_prefix = TEST_UNIT_FILE_PREFIX.c_str();
g_lib_systemd = TEST_UNIT_FILE_PREFIX.c_str();
g_etc_systemd = TEST_OUTPUT_DIR.c_str();
g_config_file = TEST_CONFIG_FILE.c_str();
char* unit_files[NUM_UNIT_FILES] = { NULL };
int num_unit_files = get_unit_files(unit_files);
// Exclude the midplane-network.service which is only used for smart switch
// Exclude the midplane-network-{npu/dpu}.service which is only used for smart switch
auto non_smart_switch_generated_services = generated_services;
non_smart_switch_generated_services.erase(
std::remove(non_smart_switch_generated_services.begin(),
non_smart_switch_generated_services.end(),
"midplane-network.service"),
"midplane-network-npu.service"),
non_smart_switch_generated_services.end());
non_smart_switch_generated_services.erase(
std::remove(non_smart_switch_generated_services.begin(),
non_smart_switch_generated_services.end(),
"midplane-network-dpu.service"),
non_smart_switch_generated_services.end());
EXPECT_EQ(num_unit_files, non_smart_switch_generated_services.size());
for (std::string service : non_smart_switch_generated_services) {

View File

@ -18,6 +18,8 @@
const char* LIB_SYSTEMD = "/usr/lib/systemd";
const char* ETC_SYSTEMD = "/etc/systemd";
const char* UNIT_FILE_PREFIX = "/usr/lib/systemd/system/";
const char* CONFIG_FILE = "/etc/sonic/generated_services.conf";
const char* MACHINE_CONF_FILE = "/host/machine.conf";
@ -25,6 +27,17 @@ const char* ASIC_CONF_FORMAT = "/usr/share/sonic/device/%s/asic.conf";
const char* PLATFORM_FILE_FORMAT = "/usr/share/sonic/device/%s/platform.json";
const char* DPU_PREFIX = "dpu";
const char* g_lib_systemd = NULL;
const char* get_lib_systemd () {
return (g_lib_systemd) ? g_lib_systemd : LIB_SYSTEMD;
}
const char* g_etc_systemd = NULL;
const char* get_etc_systemd () {
return (g_etc_systemd) ? g_etc_systemd : ETC_SYSTEMD;
}
const char* g_unit_file_prefix = NULL;
const char* get_unit_file_prefix() {
return (g_unit_file_prefix) ? g_unit_file_prefix : UNIT_FILE_PREFIX;
@ -115,6 +128,22 @@ void strip_trailing_newline(char* str) {
}
/**
* Checks if the given path is "/dev/null".
*
* @param path The path to check.
* @return true if the path is "/dev/null", false otherwise.
*/
static bool is_devnull(const char* path)
{
char resolved_path[PATH_MAX];
if (realpath(path, resolved_path) == NULL) {
return false;
}
return strcmp(resolved_path, "/dev/null") == 0;
}
static int get_target_lines(char* unit_file, char* target_lines[]) {
/***
Gets installation information for a given unit file
@ -468,11 +497,11 @@ int get_unit_files(char* unit_files[]) {
if ((strcmp(line, "topology.service") == 0) &&
(num_asics == 1)) {
continue;
}
/* midplane-network service to be started only for smart switch platform */
if ((strcmp(line, "midplane-network.service") == 0) &&
!smart_switch) {
} else if ((strcmp(line, "midplane-network-dpu.service") == 0) &&
!smart_switch_dpu) {
continue;
} else if ((strcmp(line, "midplane-network-npu.service") == 0) &&
!smart_switch_npu) {
continue;
}
@ -580,6 +609,13 @@ static int create_symlink(char* unit, char* target, char* install_dir, int insta
}
}
if (is_devnull(dest_path)) {
if (remove(dest_path) == -1) {
fprintf(stderr, "Unable to remove existing symlink %s\n", dest_path);
return -1;
}
}
r = symlink(src_path, dest_path);
if (r < 0) {
@ -873,102 +909,196 @@ static int get_num_of_dpu() {
}
static int revise_smart_switch_dependency_chain(int num_unit_files,const char* unit_files[MAX_NUM_UNITS]) {
assert(num_unit_files < MAX_NUM_UNITS);
/**
* Installs the network service.
*
* This function installs the network service by creating a symlink
* to the network service file in the appropriate directory.
*
* @param unit_name The name of the network unit to install.
* @return 0 if the network unit is installed successfully, or -1 if an error occurs.
*/
static int install_network_unit(const char* unit_name) {
assert(unit_name);
if (!smart_switch || num_unit_files <= 0) {
return 0;
const char* unit_type = strrchr(unit_name, '.');
if (unit_type == NULL) {
fprintf(stderr, "Invalid network unit %s\n", unit_name);
return -1;
}
unit_type++;
// Check the midplane-network.service is in the target list
bool found_midplane_network_service = false;
for (int i = 0; i < num_unit_files; i++) {
if (strcmp(unit_files[i], "midplane-network.service") == 0) {
found_midplane_network_service = true;
break;
}
}
if (!found_midplane_network_service) {
fprintf(stderr, "midplane-network.service is required in the target list\n");
char install_path[PATH_MAX] = {0};
char original_path[PATH_MAX] = {0};
const char* subdir;
if (strcmp(unit_type, "netdev") == 0 || strcmp(unit_type, "network") == 0) {
subdir = "/network/";
} else {
fprintf(stderr, "Invalid network unit %s\n", unit_type);
return -1;
}
// Set the midplane-network.service as before and required
const char* after_units[MAX_NUM_UNITS] = {NULL};
assert(MAX_NUM_UNITS > 3);
after_units[0] = "database.service";
if (smart_switch_npu) {
after_units[1] = "database@.service";
strcpy(install_path, get_etc_systemd());
strcat(install_path, subdir);
strcat(install_path, unit_name);
strcpy(original_path, get_lib_systemd());
strcat(original_path, subdir);
strcat(original_path, unit_name);
struct stat st;
if (stat((const char *)install_path, &st) == 0) {
// If the file already exists, remove it
if (S_ISDIR(st.st_mode)) {
fprintf(stderr, "Error: %s is a directory\n", install_path);
return -1;
}
if (remove(install_path) != 0) {
fprintf(stderr, "Error removing existing file %s\n", install_path);
return -1;
}
}
const char** unit = after_units;
static const char required_after_statements[] = "\nRequires=midplane-network.service\nAfter=midplane-network.service\n";
static const size_t required_after_statements_len = sizeof(required_after_statements) - 1;
static const char unit_tag[] = "[Unit]";
static const size_t unit_tag_len = sizeof(unit_tag) - 1;
while(*unit != NULL) {
char unit_path[PATH_MAX] = {0};
FILE *fp;
strcpy(unit_path, get_unit_file_prefix());
strcat(unit_path, *unit);
// Read all data from file
fp = fopen(unit_path, "r");
if (fp == NULL) {
fprintf(stderr, "Failed to open %s\n", unit_path);
if (is_devnull(install_path)) {
if (remove(install_path) == -1) {
fprintf(stderr, "Unable to remove existing symlink %s\n", install_path);
return -1;
}
fseek(fp, 0, SEEK_END);
long fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
size_t len = fsize + required_after_statements_len + 1;
char *data = malloc(len);
if (data == NULL) {
fprintf(stderr, "Failed to allocate memory for %s\n", unit_path);
fclose(fp);
return -1;
}
if (fread(data, fsize, 1, fp) != 1) {
fprintf(stderr, "Failed to read %s\n", unit_path);
fclose(fp);
free(data);
return -1;
}
if (symlink(original_path, install_path) != 0) {
if (errno == EEXIST)
return 0;
fprintf(stderr, "Error creating symlink %s -> %s (%s)\n", install_path, original_path, strerror(errno));
return -1;
}
return 0;
}
static int render_network_service_for_smart_switch() {
if (!smart_switch_npu) {
return 0;
}
// Render Before instruction for midplane network with database service
if (num_dpus == 0) {
return 0;
}
char buffer_instruction[MAX_BUF_SIZE] = {0};
strcpy(buffer_instruction, "\nBefore=");
for (size_t i = 0; i < num_dpus; i++) {
char *unit;
asprintf(&unit, "database@dpu%ld.service", i);
strcat(buffer_instruction, unit);
free(unit);
if (i != num_dpus - 1) {
strcat(buffer_instruction, " ");
}
}
char unit_path[PATH_MAX] = { 0 };
strcpy(unit_path, get_unit_file_prefix());
strcat(unit_path, "/midplane-network-npu.service");
FILE *fp = fopen(unit_path, "r");
if (fp == NULL) {
fprintf(stderr, "Failed to open %s\n", unit_path);
return -1;
}
fseek(fp, 0, SEEK_END);
size_t file_size = ftell(fp);
fseek(fp, 0, SEEK_SET);
size_t len = file_size + strlen(buffer_instruction) + 1;
char *unit_content = malloc(len);
if (unit_content == NULL) {
fprintf(stderr, "Failed to allocate memory for %s\n", unit_path);
}
if (fread(unit_content, file_size, 1, fp) != 1) {
fprintf(stderr, "Failed to read %s\n", unit_path);
free(unit_content);
fclose(fp);
data[fsize] = '\0';
// Check if the unit file already has the required statements
if (strstr(data, required_after_statements) != NULL) {
free(data);
unit++;
continue;
return -1;
}
fclose(fp);
// Find insert point for Before instruction
char *insert_point = strstr(unit_content, "[Unit]");
insert_point += strlen("[Unit]");
// Move the rest of the file to make room for the Before instruction
memmove(insert_point + strlen(buffer_instruction), insert_point, file_size - (insert_point - unit_content));
// Insert the Before instruction
memcpy(insert_point, buffer_instruction, strlen(buffer_instruction));
// Remove original Before instruction
insert_point += strlen(buffer_instruction);
char *before_start = strstr(insert_point, "Before=");
while (before_start != NULL) {
char *before_end = strchr(before_start, '\n');
if (before_end == NULL) {
before_end = before_start + strlen(before_start);
} else {
// Include newline character
before_end += 1;
}
// Append the required statements to the Unit section of the unit file
char *unit_section = strstr(data, unit_tag);
if (unit_section == NULL) {
fprintf(stderr, "Failed to find %s section in %s\n", unit_tag, unit_path);
free(data);
return -1;
}
unit_section += unit_tag_len;
memmove(unit_section + required_after_statements_len, unit_section, strlen(unit_section) + 1);
memcpy(unit_section, required_after_statements, required_after_statements_len);
// Write the data back to the unit file
fp = fopen(unit_path, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open %s\n", unit_path);
free(data);
return -1;
}
// Don't write the trailing '\0'
assert(len > 1);
if (fwrite(data, len - 1, 1, fp) != 1) {
fprintf(stderr, "Failed to write %s\n", unit_path);
fclose(fp);
free(data);
return -1;
const char *target_service = strstr(before_start, "database@dpu");
if (target_service != NULL && target_service < before_end) {
memmove(before_start, before_end, strlen(before_end) + 1);
} else {
before_start = before_end;
}
before_start = strstr(before_start, "Before=");
}
// Write the modified unit file
fp = fopen(unit_path, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open %s\n", unit_path);
free(unit_content);
return -1;
}
if (fwrite(unit_content, strlen(unit_content), 1, fp) != 1) {
fprintf(stderr, "Failed to write %s\n", unit_path);
free(unit_content);
fclose(fp);
free(data);
unit++;
return -1;
}
fclose(fp);
free(unit_content);
return 0;
}
static int install_network_service_for_smart_switch() {
const char** network_units = NULL;
if (smart_switch_npu) {
static const char* npu_network_units[] = {
"bridge-midplane.netdev",
"bridge-midplane.network",
"midplane-network-npu.network",
NULL
};
network_units = npu_network_units;
} else if (smart_switch_dpu) {
static const char* dpu_network_units[] = {
"midplane-network-dpu.network",
NULL
};
network_units = dpu_network_units;
} else {
return -1;
}
if (network_units == NULL) {
return 0;
}
while(*network_units) {
if (install_network_unit(*network_units) != 0) {
return -1;
}
network_units++;
}
return 0;
@ -1006,10 +1136,13 @@ int ssg_main(int argc, char **argv) {
strcat(install_dir, "/");
num_unit_files = get_unit_files(unit_files);
// Revise dependency chain for smart switch
// Install and render midplane network service for smart switch
if (smart_switch) {
if (revise_smart_switch_dependency_chain(num_unit_files, (const char **)unit_files) != 0) {
return 1;
if (render_network_service_for_smart_switch() != 0) {
return -1;
}
if (install_network_service_for_smart_switch() != 0) {
return -1;
}
}

View File

@ -16,6 +16,8 @@ extern const char* CONFIG_FILE;
extern const char* MACHINE_CONF_FILE;
extern const char* ASIC_CONF_FORMAT;
extern const char* PLATFORM_FILE_FORMAT;
extern const char* g_lib_systemd;
extern const char* g_etc_systemd;
extern const char* g_unit_file_prefix;
extern const char* g_config_file;
extern const char* g_machine_config_file;

View File

@ -0,0 +1 @@
../../../../files/image_config/midplane-network/bridge-midplane.netdev

View File

@ -0,0 +1 @@
../../../../files/image_config/midplane-network/bridge-midplane.network

View File

@ -0,0 +1 @@
../../../../files/image_config/midplane-network/midplane-network-dpu.network

View File

@ -0,0 +1 @@
../../../../files/image_config/midplane-network/midplane-network-dpu.service

View File

@ -0,0 +1 @@
../../../../files/image_config/midplane-network/midplane-network-npu.network

View File

@ -0,0 +1 @@
../../../../files/image_config/midplane-network/midplane-network-npu.service

View File

@ -1,12 +0,0 @@
[Unit]
Description=Initialize midplane network for smart switch
StartLimitIntervalSec=1200
StartLimitBurst=3
[Service]
ExecStart=/usr/bin/test.sh wait
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.target