syncd/MdioIpcClient.cpp (200 lines of code) (raw):

/* Includes */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/socket.h> #include <sys/un.h> #include <unistd.h> #include <time.h> #include <pthread.h> #include <mutex> #include "MdioIpcClient.h" #include "MdioIpcCommon.h" #include "swss/logger.h" static std::mutex ipcMutex; /* Global variables */ static int syncd_mdio_ipc_command(char *cmd, char *resp) { // SWSS_LOG_ENTER(); // disabled int fd; ssize_t ret; size_t len; struct sockaddr_un saddr, caddr; static int sock = 0; static char path[128] = { 0 }; static time_t timeout = 0; if (timeout < time(NULL)) { /* It might already be timed out at the server side, reconnect ... */ if (sock > 0) { close(sock); } sock = 0; } if (strlen(path) == 0) { strcpy(path, SYNCD_IPC_SOCK_SYNCD); fd = open(path, O_DIRECTORY); if (fd < 0) { SWSS_LOG_INFO("Program is not run on host\n"); strcpy(path, SYNCD_IPC_SOCK_HOST); fd = open(path, O_DIRECTORY); if (fd < 0) { SWSS_LOG_ERROR("Unable to open the directory for IPC\n"); return errno; } } } if (sock <= 0) { sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { SWSS_LOG_ERROR("socket() :%s", strerror(errno)); return errno; } caddr.sun_family = AF_UNIX; snprintf(caddr.sun_path, sizeof(caddr.sun_path), "%s/%s.cli.%d", path, SYNCD_IPC_SOCK_FILE, getpid()); unlink(caddr.sun_path); if (bind(sock, (struct sockaddr *)&caddr, sizeof(caddr)) < 0) { SWSS_LOG_ERROR("bind() :%s", strerror(errno)); close(sock); sock = 0; return errno; } saddr.sun_family = AF_UNIX; snprintf(saddr.sun_path, sizeof(saddr.sun_path), "%s/%s.srv", path, SYNCD_IPC_SOCK_FILE); if (connect(sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) { SWSS_LOG_ERROR("connect() :%s", strerror(errno)); close(sock); sock = 0; unlink(caddr.sun_path); return errno; } } len = strlen(cmd); ret = send(sock, cmd, len, 0); if (ret < (ssize_t)len) { SWSS_LOG_ERROR("send failed, ret=%ld, expected=%ld\n", ret, len); close(sock); sock = 0; unlink(caddr.sun_path); return -EIO; } ret = recv(sock, resp, SYNCD_IPC_BUFF_SIZE - 1, 0); if (ret <= 0) { SWSS_LOG_ERROR("recv failed, ret=%ld\n", ret); close(sock); sock = 0; unlink(caddr.sun_path); return -EIO; } timeout = time(NULL) + MDIO_CLIENT_TIMEOUT; return (int)strtol(resp, NULL, 0); } /* Function to read data from MDIO interface */ sai_status_t mdio_read(uint64_t platform_context, uint32_t mdio_addr, uint32_t reg_addr, uint32_t number_of_registers, uint32_t *data) { // SWSS_LOG_ENTER(); // disabled int rc = SAI_STATUS_FAILURE; char cmd[SYNCD_IPC_BUFF_SIZE], resp[SYNCD_IPC_BUFF_SIZE]; if (number_of_registers > 1) { SWSS_LOG_ERROR("Multiple register reads are not supported, num_of_registers: %d\n", number_of_registers); return SAI_STATUS_FAILURE; } ipcMutex.lock(); sprintf(cmd, "mdio 0x%x 0x%x\n", mdio_addr, reg_addr); rc = syncd_mdio_ipc_command(cmd, resp); if (rc == 0) { *data = (uint32_t)strtoul(strchrnul(resp, ' ') + 1, NULL, 0); rc = SAI_STATUS_SUCCESS; } else { SWSS_LOG_ERROR("syncd_mdio_ipc_command returns : %d\n", rc); } ipcMutex.unlock(); return rc; } /* Function to write data to MDIO interface */ sai_status_t mdio_write(uint64_t platform_context, uint32_t mdio_addr, uint32_t reg_addr, uint32_t number_of_registers, const uint32_t *data) { // SWSS_LOG_ENTER(); // disabled int rc = SAI_STATUS_FAILURE; char cmd[SYNCD_IPC_BUFF_SIZE], resp[SYNCD_IPC_BUFF_SIZE]; if (number_of_registers > 1) { SWSS_LOG_ERROR("Multiple register reads are not supported, num_of_registers: %d\n", number_of_registers); return SAI_STATUS_FAILURE; } ipcMutex.lock(); sprintf(cmd, "mdio 0x%x 0x%x 0x%x\n", mdio_addr, reg_addr, *data); rc = syncd_mdio_ipc_command(cmd, resp); if (rc == 0) { rc = SAI_STATUS_SUCCESS; } else { SWSS_LOG_ERROR("syncd_mdio_ipc_command returns : %d\n", rc); } ipcMutex.unlock(); return rc; } /* Function to read data using clause 22 from MDIO interface */ sai_status_t mdio_read_cl22(uint64_t platform_context, uint32_t mdio_addr, uint32_t reg_addr, uint32_t number_of_registers, uint32_t *data) { // SWSS_LOG_ENTER(); // disabled int rc = SAI_STATUS_FAILURE; char cmd[SYNCD_IPC_BUFF_SIZE], resp[SYNCD_IPC_BUFF_SIZE]; if (number_of_registers > 1) { SWSS_LOG_ERROR("Multiple register reads are not supported, num_of_registers: %d\n", number_of_registers); return SAI_STATUS_FAILURE; } ipcMutex.lock(); sprintf(cmd, "mdio-cl22 0x%x 0x%x\n", mdio_addr, reg_addr); rc = syncd_mdio_ipc_command(cmd, resp); if (rc == 0) { *data = (uint32_t)strtoul(strchrnul(resp, ' ') + 1, NULL, 0); rc = SAI_STATUS_SUCCESS; } else { SWSS_LOG_ERROR("syncd_mdio_ipc_command returns : %d\n", rc); } ipcMutex.unlock(); return rc; } /* Function to write data using clause 22 to MDIO interface */ sai_status_t mdio_write_cl22(uint64_t platform_context, uint32_t mdio_addr, uint32_t reg_addr, uint32_t number_of_registers, const uint32_t *data) { // SWSS_LOG_ENTER(); // disabled int rc = SAI_STATUS_FAILURE; char cmd[SYNCD_IPC_BUFF_SIZE], resp[SYNCD_IPC_BUFF_SIZE]; if (number_of_registers > 1) { SWSS_LOG_ERROR("Multiple register reads are not supported, num_of_registers: %d\n", number_of_registers); return SAI_STATUS_FAILURE; } ipcMutex.lock(); sprintf(cmd, "mdio-cl22 0x%x 0x%x 0x%x\n", mdio_addr, reg_addr, *data); rc = syncd_mdio_ipc_command(cmd, resp); if (rc == 0) { rc = SAI_STATUS_SUCCESS; } else { SWSS_LOG_ERROR("syncd_mdio_ipc_command returns : %d\n", rc); } ipcMutex.unlock(); return rc; }