* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "datasystem/common/rdma/rdma_util.h"
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <net/if.h>
#include "datasystem/common/log/log.h"
#include "datasystem/common/util/gflag/common_gflags.h"
#include "datasystem/common/util/status_helper.h"
namespace datasystem {
static constexpr int RDMA_LOG_LEVEL = 3;
const int OCTET = 8;
const int IP_NUM_OCTETS = 4;
const int IPV4_MAX_LENGTH = 16;
Status GetDevNameFromDestIp(const std::string &ipAddr, std::string &devName)
{
std::istringstream iss(ipAddr);
std::string nextToken;
int num[4];
for (int i = 0; std::getline(iss, nextToken, '.'); i++) {
num[i] = atoi(nextToken.c_str());
}
unsigned long ip = 0;
for (int i = 0; i < IP_NUM_OCTETS; i++) {
ip += num[i] << (OCTET * i);
}
VLOG(RDMA_LOG_LEVEL) << FormatString("%lu\n", ip);
char devname[64];
unsigned long d, g, m;
int r, flgs, ref, use, metric, mtu, win, ir;
std::string path("/proc/net/route");
FILE *fp = fopen(path.c_str(), "r");
RETURN_RUNTIME_ERROR_IF_NULL(fp);
r = fscanf_s(fp, "%*[^\n]\n");
* is completely empty, /proc/net/route has no header.
*/
CHECK_FAIL_RETURN_STATUS(r >= 0, K_RUNTIME_ERROR, "Empty line, read error, or EOF");
bool found = false;
while (!found) {
r = fscanf_s(fp, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n", devname, sizeof(devname), &d, &g, &flgs, &ref, &use, &metric,
&m, &mtu, &win, &ir);
if (r != EAGAIN) {
if ((r < 0) && feof(fp)) {
break;
}
}
if (!(flgs & 0x0001)) {
continue;
}
VLOG(RDMA_LOG_LEVEL) << FormatString("devname=%s,dest=%lld,gw=%lld,mask=%lld\n", devname, d, g, m);
devName = std::string(devname);
if ((d & m) == (ip & m) && (d & m) != 0) {
VLOG(RDMA_LOG_LEVEL) << FormatString("find success devname=%s\n", devname);
found = true;
}
}
if (!found) {
LOG(WARNING) << FormatString("Device name of %s is not found. Will use device name: %s", ipAddr, devName);
}
(void)fclose(fp);
return Status::OK();
}
void *GetInterfaceInAddr(struct ifaddrs *ifa)
{
if (ifa->ifa_addr->sa_family == AF_INET) {
return &((reinterpret_cast<struct sockaddr_in *>(ifa->ifa_addr))->sin_addr);
}
return &((reinterpret_cast<struct sockaddr_in6 *>(ifa->ifa_addr))->sin6_addr);
}
int GetDevNameFromLocalIp(const std::string &ipAddr, std::string &devName)
{
struct ifaddrs *ifaddr, *ifa;
int family;
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
return 1;
}
bool found = false;
uint32_t expectedFlags = IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_MULTICAST;
for (ifa = ifaddr; ifa != NULL && found == false; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
continue;
family = ifa->ifa_addr->sa_family;
if ((family == AF_INET || family == AF_INET6) && (expectedFlags & ifa->ifa_flags) == expectedFlags) {
devName = std::string(ifa->ifa_name);
std::string inetRes(INET6_ADDRSTRLEN, 0);
if (0 == strcmp(ipAddr.c_str(), inet_ntop(ifa->ifa_addr->sa_family, GetInterfaceInAddr(ifa),
const_cast<char *>(inetRes.c_str()), inetRes.size()))) {
VLOG(RDMA_LOG_LEVEL) << FormatString("find success devname=%s\n", ifa->ifa_name);
found = true;
}
}
}
freeifaddrs(ifaddr);
if (!found) {
LOG(WARNING) << FormatString(
"Device name of %s is either not found or not matching flags. Will use device name: %s", ipAddr, devName);
}
return 0;
}
}