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 <yuhsingw@google.com> Maintainer: Gabe Black <gabeblack@google.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -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)
|
||||
{}
|
||||
|
||||
@@ -159,6 +159,8 @@ class ListenSocketConfig
|
||||
|
||||
operator bool() const { return (bool)builder; }
|
||||
|
||||
static bool parseIni(const std::string &value, ListenSocketConfig &retval);
|
||||
|
||||
private:
|
||||
Builder builder;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_<ListenSocketConfig>(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
|
||||
|
||||
Reference in New Issue
Block a user