Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to specify grpc host #18193

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
grpc: add ability to specify grpc host
This update lets you specify the network interface for gRPC.
For example, using 127.0.0.1 restricts gRPC access to the local machine, enhancing security since gRPC is not publicly exposed.
For backward compatibility, the default remains 0.0.0.0.

Signed-off-by: Vladimir Buyanov <b.vladimir@clickadu.com>
  • Loading branch information
cl-bvl committed Feb 19, 2025
commit 45e10c77f221d7ae5a72995f7a0d0dbea66bd76b
2 changes: 1 addition & 1 deletion doc/developer/grpc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Northbound gRPC
To enable gRPC support one needs to add `--enable-grpc` when running
`configure`. Additionally, when launching each daemon one needs to request
the gRPC module be loaded and which port to bind to. This can be done by adding
`-M grpc:<port>` to the daemon's CLI arguments.
`-M grpc:<host>:<port>` or `-M grpc:<port>` (default host is `0.0.0.0`) to the daemon's CLI arguments.

Currently there is no gRPC "routing" so you will need to bind your gRPC
`channel` to the particular daemon's gRPC port to interact with that daemon's
Expand Down
70 changes: 53 additions & 17 deletions lib/northbound_grpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1131,18 +1131,15 @@ static grpc::Server *s_server;
static void *grpc_pthread_start(void *arg)
{
struct frr_pthread *fpt = static_cast<frr_pthread *>(arg);
uint port = (uint) reinterpret_cast<intptr_t>(fpt->data);
std::string endpoint = *static_cast<std::string *>(fpt->data);

Candidates candidates;
grpc::ServerBuilder builder;
std::stringstream server_address;
frr::Northbound::AsyncService service;

frr_pthread_set_name(fpt);

server_address << "0.0.0.0:" << port;
builder.AddListeningPort(server_address.str(),
grpc::InsecureServerCredentials());
builder.AddListeningPort(endpoint, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
builder.AddChannelArgument(
GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS, 5000);
Expand Down Expand Up @@ -1172,8 +1169,7 @@ static void *grpc_pthread_start(void *arg)
REQUEST_NEWRPC_STREAMING(Get);
REQUEST_NEWRPC_STREAMING(ListTransactions);

zlog_notice("gRPC server listening on %s",
server_address.str().c_str());
zlog_notice("gRPC server listening on %s", endpoint.c_str());

/* Process inbound RPCs */
bool ok;
Expand Down Expand Up @@ -1225,7 +1221,7 @@ static void *grpc_pthread_start(void *arg)
}


static int frr_grpc_init(uint port)
static int frr_grpc_init(const std::string &endpoint)
{
struct frr_pthread_attr attr = {
.start = grpc_pthread_start,
Expand All @@ -1235,12 +1231,14 @@ static int frr_grpc_init(uint port)
grpc_debug("%s: entered", __func__);

fpt = frr_pthread_new(&attr, "frr-grpc", "frr-grpc");
fpt->data = reinterpret_cast<void *>((intptr_t)port);
std::string *ep = new std::string(endpoint);
fpt->data = reinterpret_cast<void *>(ep);

/* Create a pthread for gRPC since it runs its own event loop. */
if (frr_pthread_run(fpt, NULL) < 0) {
flog_err(EC_LIB_SYSTEM_CALL, "%s: error creating pthread: %s",
__func__, safe_strerror(errno));
delete ep;
return -1;
}

Expand Down Expand Up @@ -1288,19 +1286,57 @@ static int frr_grpc_finish(void)
static void frr_grpc_module_very_late_init(struct event *thread)
{
const char *args = THIS_MODULE->load_args;
uint port = GRPC_DEFAULT_PORT;
std::string endpoint;

if (args) {
port = std::stoul(args);
if (port < 1024 || port > UINT16_MAX) {
flog_err(EC_LIB_GRPC_INIT,
"%s: port number must be between 1025 and %d",
__func__, UINT16_MAX);
goto error;
std::string arg_str(args);

if (arg_str.find(':') != std::string::npos) {
size_t pos = arg_str.rfind(':');
std::string port_str = arg_str.substr(pos + 1);
uint port = 0;
try {
port = std::stoul(port_str);
} catch (const std::exception &e) {
flog_err(EC_LIB_GRPC_INIT,
"%s: invalid port number in host:port format: %s",
__func__, e.what());
goto error;
}

if (port < 1024 || port > UINT16_MAX) {
flog_err(EC_LIB_GRPC_INIT,
"%s: port number must be between 1025 and %d", __func__,
UINT16_MAX);
goto error;
}
endpoint = arg_str;
} else {
if (!arg_str.empty() && arg_str[0] == ':')
arg_str = arg_str.substr(1);

uint port = 0;
try {
port = std::stoul(arg_str);
} catch (const std::exception &e) {
flog_err(EC_LIB_GRPC_INIT, "%s: invalid port number: %s", __func__,
e.what());
goto error;
}

if (port < 1024 || port > UINT16_MAX) {
flog_err(EC_LIB_GRPC_INIT,
"%s: port number must be between 1025 and %d", __func__,
UINT16_MAX);
goto error;
}
endpoint = "0.0.0.0:" + arg_str;
}
} else {
endpoint = "0.0.0.0:" + std::to_string(GRPC_DEFAULT_PORT);
}

if (frr_grpc_init(port) < 0)
if (frr_grpc_init(endpoint) < 0)
goto error;

return;
Expand Down
Loading