From 57aaccdeff83543193079dea51e90d9b28024087 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Sat, 18 Mar 2023 20:25:11 -0700 Subject: [PATCH] base,python: Add a param type for host sockets. These can either be set to an integer, in which case it's interpreted as a TCP port, or a string, in which case it's treated as a unix domain socket. If the unix domain socket is prefixed with a "@", it will be treated as an abstract socket. When stored in the ini file, there is always a prefix added to make parsing the string more systematic and less ambiguous. A port number is prefixed with "#", an abstract socket with "@", and a socket file with the prefix "P" for "path". Change-Id: I1fc7a579074e849b3becd936238c62fb0d9a2087 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/69165 Reviewed-by: Yu-hsin Wang Maintainer: Gabe Black Tested-by: kokoro --- src/base/socket.cc | 26 ++++++++++++++++ src/base/socket.hh | 2 ++ src/python/m5/params.py | 59 +++++++++++++++++++++++++++++++++++++ src/python/pybind11/core.cc | 15 ++++++++++ 4 files changed, 102 insertions(+) diff --git a/src/base/socket.cc b/src/base/socket.cc index 0f47b2ab13..a30c6af446 100644 --- a/src/base/socket.cc +++ b/src/base/socket.cc @@ -208,6 +208,32 @@ ListenSocket::accept() return sfd; } +bool +ListenSocketConfig::parseIni(const std::string &value, + ListenSocketConfig &retval) +{ + if (value.size() == 0) { + retval = listenSocketEmptyConfig(); + return true; + } else if (value[0] == '@') { + retval = listenSocketUnixAbstractConfig(value.substr(1)); + return true; + } else if (value[0] == 'P') { + std::filesystem::path p(value.substr(1)); + retval = listenSocketUnixFileConfig(p.parent_path(), p.filename()); + return true; + } else if (value[0] == '#') { + uint64_t port; + bool ret = to_number(value.substr(1), port); + if (!ret) + return false; + retval = listenSocketInetConfig(port); + return true; + } else { + panic("Can't interpret %s as a host socket.", value); + } +} + ListenSocketInet::ListenSocketInet(const std::string &_name, int port) : ListenSocket(_name), _port(port) {} diff --git a/src/base/socket.hh b/src/base/socket.hh index 33c1c3a3cb..5ae02aa103 100644 --- a/src/base/socket.hh +++ b/src/base/socket.hh @@ -159,6 +159,8 @@ class ListenSocketConfig operator bool() const { return (bool)builder; } + static bool parseIni(const std::string &value, ListenSocketConfig &retval); + private: Builder builder; }; diff --git a/src/python/m5/params.py b/src/python/m5/params.py index e9047a85d4..2ca6dfcc14 100644 --- a/src/python/m5/params.py +++ b/src/python/m5/params.py @@ -1085,6 +1085,65 @@ class Bool(ParamValue): code(f"{ret} to_bool({src}, {dest});") +class HostSocket(ParamValue): + cxx_type = "ListenSocketConfig" + + @classmethod + def cxx_predecls(cls, code): + code('#include "base/socket.hh"') + + def __init__(self, value): + if isinstance(value, HostSocket): + self.value = value.value + else: + self.value = value + + def getValue(self): + from _m5.socket import listenSocketEmptyConfig + from _m5.socket import listenSocketInetConfig + from _m5.socket import listenSocketUnixFileConfig + from _m5.socket import listenSocketUnixAbstractConfig + + if isinstance(self.value, str): + if self.value[0] == "@": + return listenSocketUnixAbstractConfig(self.value[1:]) + else: + d, f = os.path.split(self.value) + return listenSocketUnixFileConfig(d, f) + else: + if self.value == 0: + return listenSocketEmptyConfig() + else: + return listenSocketInetConfig(self.value) + + def __call__(self, value): + self.__init__(value) + return value + + def __str__(self): + if isinstance(self.value, str): + return self.value + else: + return "#" + str(self.value) + + def ini_str(self): + if isinstance(self.value, str): + if self.value[0] == "@": + return self.value + else: + return "P" + self.value + else: + return "#" + str(self.value) + + @classmethod + def cxx_ini_predecls(cls, code): + code('#include "base/socket.hh"') + + @classmethod + def cxx_ini_parse(cls, code, src, dest, ret): + code(f"{ret} ListenSocketConfig::parseIni({src}, {dest});") + + def IncEthernetAddr(addr, val=1): bytes = [int(x, 16) for x in addr.split(":")] bytes[5] += val diff --git a/src/python/pybind11/core.cc b/src/python/pybind11/core.cc index bd83a74331..0b03d5a13b 100644 --- a/src/python/pybind11/core.cc +++ b/src/python/pybind11/core.cc @@ -223,6 +223,20 @@ init_loader(py::module_ &m_native) m.def("setInterpDir", &loader::setInterpDir); } +static void +init_socket(py::module_ &m_native) +{ + py::module_ m_socket = m_native.def_submodule("socket"); + m_socket + .def("listenSocketEmptyConfig", &listenSocketEmptyConfig) + .def("listenSocketInetConfig", &listenSocketInetConfig) + .def("listenSocketUnixFileConfig", &listenSocketUnixFileConfig) + .def("listenSocketUnixAbstractConfig", + &listenSocketUnixAbstractConfig); + + py::class_(m_socket, "ListenSocketConfig"); +} + void pybind_init_core(py::module_ &m_native) { @@ -334,6 +348,7 @@ pybind_init_core(py::module_ &m_native) init_net(m_native); init_loader(m_native); init_pc(m_native); + init_socket(m_native); } } // namespace gem5