Skip to content

Commit c223742

Browse files
authored
Add mdio IPC client library (#1230)
Signed-off-by: Jiahua Wang <[email protected]> Why I did it The syncd has a MDIO IPC server to help the access of external PHYs on the NPU MDIO bus. A MDIO IPC client library is required to communicate to the MDIO IPC server. The gbsyncd will pass the function pointers for the function in the client library to the PAI. How I did it MDIO IPC client functions are added to connect to the MDIO IPC server socket, to send request and to wait for response IPC messages. The client functions are made into a .so library. The .so library is packaged in the syncd debian package. How to verify it The client functions are also available in as a .a library. The unit test code can use the code to test both IPC server and client.
1 parent dc93d4c commit c223742

17 files changed

Lines changed: 795 additions & 25 deletions

.azure-pipelines/build-template.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ jobs:
9595
sudo sed -ri 's/^unixsocketperm .../unixsocketperm 777/' /etc/redis/redis.conf
9696
sudo sed -ri 's/redis-server.sock/redis.sock/' /etc/redis/redis.conf
9797
sudo service redis-server start
98+
sudo mkdir -m 755 /var/run/sswsyncd
9899
99100
sudo apt-get install -y rsyslog
100101
sudo service rsyslog start
@@ -180,6 +181,8 @@ jobs:
180181
set -ex
181182
# Add SYS_TIME capability for settimeofday ok in syncd test
182183
sudo setcap "cap_sys_time=eip" syncd/.libs/syncd_tests
184+
# Add CAP_DAC_OVERRIDE capability for system directory creation in syncd unittest
185+
sudo setcap "cap_dac_override,cap_ipc_lock,cap_ipc_owner,cap_sys_time=eip" unittest/syncd/.libs/tests
183186
make check
184187
gcovr --version
185188
find SAI/meta -name "*.gc*" | xargs rm -vf

debian/syncd.dirs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
usr/bin
2+
usr/lib

debian/syncd.install

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ usr/bin/saidiscovery
55
usr/bin/saiasiccmp
66
usr/bin/syncd*
77
syncd/scripts/* usr/bin
8+
usr/lib/*/libMdioIpcClient.so.*

debian/syncd.links

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#! /usr/bin/dh-exec
2+
/usr/lib/${DEB_HOST_MULTIARCH}/libMdioIpcClient.so.0 /usr/lib/${DEB_HOST_MULTIARCH}/libMdioIpcClient.so

meta/DummySaiInterface.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,54 @@ sai_status_t DummySaiInterface::flushFdbEntries(
131131
return m_status;
132132
}
133133

134+
sai_status_t DummySaiInterface::switchMdioRead(
135+
_In_ sai_object_id_t switchId,
136+
_In_ uint32_t device_addr,
137+
_In_ uint32_t start_reg_addr,
138+
_In_ uint32_t number_of_registers,
139+
_Out_ uint32_t *reg_val)
140+
{
141+
SWSS_LOG_ENTER();
142+
143+
return m_status;
144+
}
145+
146+
sai_status_t DummySaiInterface::switchMdioWrite(
147+
_In_ sai_object_id_t switchId,
148+
_In_ uint32_t device_addr,
149+
_In_ uint32_t start_reg_addr,
150+
_In_ uint32_t number_of_registers,
151+
_In_ const uint32_t *reg_val)
152+
{
153+
SWSS_LOG_ENTER();
154+
155+
return m_status;
156+
}
157+
158+
sai_status_t DummySaiInterface::switchMdioCl22Read(
159+
_In_ sai_object_id_t switchId,
160+
_In_ uint32_t device_addr,
161+
_In_ uint32_t start_reg_addr,
162+
_In_ uint32_t number_of_registers,
163+
_Out_ uint32_t *reg_val)
164+
{
165+
SWSS_LOG_ENTER();
166+
167+
return m_status;
168+
}
169+
170+
sai_status_t DummySaiInterface::switchMdioCl22Write(
171+
_In_ sai_object_id_t switchId,
172+
_In_ uint32_t device_addr,
173+
_In_ uint32_t start_reg_addr,
174+
_In_ uint32_t number_of_registers,
175+
_In_ const uint32_t *reg_val)
176+
{
177+
SWSS_LOG_ENTER();
178+
179+
return m_status;
180+
}
181+
134182
sai_status_t DummySaiInterface::objectTypeGetAvailability(
135183
_In_ sai_object_id_t switchId,
136184
_In_ sai_object_type_t objectType,

meta/DummySaiInterface.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,34 @@ namespace saimeta
145145
_In_ uint32_t attrCount,
146146
_In_ const sai_attribute_t *attrList) override;
147147

148+
virtual sai_status_t switchMdioRead(
149+
_In_ sai_object_id_t switchId,
150+
_In_ uint32_t device_addr,
151+
_In_ uint32_t start_reg_addr,
152+
_In_ uint32_t number_of_registers,
153+
_Out_ uint32_t *reg_val) override;
154+
155+
virtual sai_status_t switchMdioWrite(
156+
_In_ sai_object_id_t switchId,
157+
_In_ uint32_t device_addr,
158+
_In_ uint32_t start_reg_addr,
159+
_In_ uint32_t number_of_registers,
160+
_In_ const uint32_t *reg_val) override;
161+
162+
virtual sai_status_t switchMdioCl22Read(
163+
_In_ sai_object_id_t switchId,
164+
_In_ uint32_t device_addr,
165+
_In_ uint32_t start_reg_addr,
166+
_In_ uint32_t number_of_registers,
167+
_Out_ uint32_t *reg_val) override;
168+
169+
virtual sai_status_t switchMdioCl22Write(
170+
_In_ sai_object_id_t switch_id,
171+
_In_ uint32_t device_addr,
172+
_In_ uint32_t start_reg_addr,
173+
_In_ uint32_t number_of_registers,
174+
_In_ const uint32_t *reg_val) override;
175+
148176
public: // SAI API
149177

150178
virtual sai_status_t objectTypeGetAvailability(

syncd/Makefile.am

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ endif
1010

1111
bin_PROGRAMS = syncd syncd_request_shutdown syncd_tests
1212

13-
noinst_LIBRARIES = libSyncd.a libSyncdRequestShutdown.a
13+
lib_LTLIBRARIES = libMdioIpcClient.la
14+
15+
noinst_LIBRARIES = libSyncd.a libSyncdRequestShutdown.a libMdioIpcClient.a
1416

1517
libSyncd_a_SOURCES = \
1618
AsicOperation.cpp \
@@ -91,6 +93,17 @@ syncd_request_shutdown_CPPFLAGS = $(CODE_COVERAGE_CPPFLAGS)
9193
syncd_request_shutdown_CXXFLAGS = $(DBGFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS_COMMON) $(CODE_COVERAGE_CXXFLAGS)
9294
syncd_request_shutdown_LDADD = libSyncdRequestShutdown.a $(top_srcdir)/lib/libSaiRedis.a -lhiredis -lswsscommon -lpthread $(CODE_COVERAGE_LIBS)
9395

96+
libMdioIpcClient_a_SOURCES = MdioIpcClient.cpp
97+
98+
libMdioIpcClient_la_SOURCES = MdioIpcClient.cpp
99+
100+
libMdioIpcClient_a_CPPFLAGS = $(CODE_COVERAGE_CPPFLAGS) -Wno-format-truncation
101+
libMdioIpcClient_a_CXXFLAGS = $(DBGFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS_COMMON) $(CODE_COVERAGE_CXXFLAGS)
102+
103+
libMdioIpcClient_la_CPPFLAGS = $(CODE_COVERAGE_CPPFLAGS) -Wno-format-truncation
104+
libMdioIpcClient_la_CXXFLAGS = $(DBGFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS_COMMON) $(CODE_COVERAGE_CXXFLAGS)
105+
libMdioIpcClient_la_LIBADD = -lswsscommon $(CODE_COVERAGE_LIBS)
106+
94107
syncd_tests_SOURCES = tests.cpp
95108
syncd_tests_CXXFLAGS = $(DBGFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS_COMMON)
96109
syncd_tests_LDFLAGS = -Wl,-rpath,$(top_srcdir)/lib/.libs -Wl,-rpath,$(top_srcdir)/meta/.libs

syncd/MdioIpcClient.cpp

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
/* Includes */
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <stdint.h>
5+
#include <errno.h>
6+
#include <string.h>
7+
#include <sys/types.h>
8+
#include <sys/stat.h>
9+
#include <fcntl.h>
10+
#include <sys/socket.h>
11+
#include <sys/un.h>
12+
#include <unistd.h>
13+
#include <time.h>
14+
#include <pthread.h>
15+
#include <mutex>
16+
17+
#include "MdioIpcClient.h"
18+
#include "MdioIpcCommon.h"
19+
20+
#include "swss/logger.h"
21+
22+
static std::mutex ipcMutex;
23+
24+
/* Global variables */
25+
26+
static int syncd_mdio_ipc_command(char *cmd, char *resp)
27+
{
28+
// SWSS_LOG_ENTER(); // disabled
29+
30+
int fd;
31+
ssize_t ret;
32+
size_t len;
33+
struct sockaddr_un saddr, caddr;
34+
static int sock = 0;
35+
static char path[128] = { 0 };
36+
static time_t timeout = 0;
37+
38+
if (timeout < time(NULL))
39+
{
40+
/* It might already be timed out at the server side, reconnect ... */
41+
if (sock > 0)
42+
{
43+
close(sock);
44+
}
45+
sock = 0;
46+
}
47+
48+
if (strlen(path) == 0)
49+
{
50+
strcpy(path, SYNCD_IPC_SOCK_SYNCD);
51+
fd = open(path, O_DIRECTORY);
52+
if (fd < 0)
53+
{
54+
SWSS_LOG_INFO("Program is not run on host\n");
55+
strcpy(path, SYNCD_IPC_SOCK_HOST);
56+
fd = open(path, O_DIRECTORY);
57+
if (fd < 0)
58+
{
59+
SWSS_LOG_ERROR("Unable to open the directory for IPC\n");
60+
return errno;
61+
}
62+
}
63+
}
64+
65+
if (sock <= 0)
66+
{
67+
sock = socket(AF_UNIX, SOCK_STREAM, 0);
68+
if (sock < 0)
69+
{
70+
SWSS_LOG_ERROR("socket() :%s", strerror(errno));
71+
return errno;
72+
}
73+
74+
caddr.sun_family = AF_UNIX;
75+
snprintf(caddr.sun_path, sizeof(caddr.sun_path), "%s/%s.cli.%d", path, SYNCD_IPC_SOCK_FILE, getpid());
76+
unlink(caddr.sun_path);
77+
if (bind(sock, (struct sockaddr *)&caddr, sizeof(caddr)) < 0)
78+
{
79+
SWSS_LOG_ERROR("bind() :%s", strerror(errno));
80+
close(sock);
81+
sock = 0;
82+
return errno;
83+
}
84+
85+
saddr.sun_family = AF_UNIX;
86+
snprintf(saddr.sun_path, sizeof(saddr.sun_path), "%s/%s.srv", path, SYNCD_IPC_SOCK_FILE);
87+
if (connect(sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0)
88+
{
89+
SWSS_LOG_ERROR("connect() :%s", strerror(errno));
90+
close(sock);
91+
sock = 0;
92+
unlink(caddr.sun_path);
93+
return errno;
94+
}
95+
}
96+
97+
len = strlen(cmd);
98+
ret = send(sock, cmd, len, 0);
99+
if (ret < (ssize_t)len)
100+
{
101+
SWSS_LOG_ERROR("send failed, ret=%ld, expected=%ld\n", ret, len);
102+
close(sock);
103+
sock = 0;
104+
unlink(caddr.sun_path);
105+
return -EIO;
106+
}
107+
108+
ret = recv(sock, resp, SYNCD_IPC_BUFF_SIZE - 1, 0);
109+
if (ret <= 0)
110+
{
111+
SWSS_LOG_ERROR("recv failed, ret=%ld\n", ret);
112+
close(sock);
113+
sock = 0;
114+
unlink(caddr.sun_path);
115+
return -EIO;
116+
}
117+
118+
timeout = time(NULL) + MDIO_CLIENT_TIMEOUT;
119+
return (int)strtol(resp, NULL, 0);
120+
}
121+
122+
123+
/* Function to read data from MDIO interface */
124+
sai_status_t mdio_read(uint64_t platform_context, uint32_t mdio_addr, uint32_t reg_addr,
125+
uint32_t number_of_registers, uint32_t *data)
126+
{
127+
// SWSS_LOG_ENTER(); // disabled
128+
129+
int rc = SAI_STATUS_FAILURE;
130+
char cmd[SYNCD_IPC_BUFF_SIZE], resp[SYNCD_IPC_BUFF_SIZE];
131+
132+
if (number_of_registers > 1)
133+
{
134+
SWSS_LOG_ERROR("Multiple register reads are not supported, num_of_registers: %d\n", number_of_registers);
135+
return SAI_STATUS_FAILURE;
136+
}
137+
138+
ipcMutex.lock();
139+
140+
sprintf(cmd, "mdio 0x%x 0x%x\n", mdio_addr, reg_addr);
141+
rc = syncd_mdio_ipc_command(cmd, resp);
142+
if (rc == 0)
143+
{
144+
*data = (uint32_t)strtoul(strchrnul(resp, ' ') + 1, NULL, 0);
145+
rc = SAI_STATUS_SUCCESS;
146+
}
147+
else
148+
{
149+
SWSS_LOG_ERROR("syncd_mdio_ipc_command returns : %d\n", rc);
150+
}
151+
152+
ipcMutex.unlock();
153+
return rc;
154+
}
155+
156+
/* Function to write data to MDIO interface */
157+
sai_status_t mdio_write(uint64_t platform_context, uint32_t mdio_addr, uint32_t reg_addr,
158+
uint32_t number_of_registers, const uint32_t *data)
159+
{
160+
// SWSS_LOG_ENTER(); // disabled
161+
162+
int rc = SAI_STATUS_FAILURE;
163+
char cmd[SYNCD_IPC_BUFF_SIZE], resp[SYNCD_IPC_BUFF_SIZE];
164+
165+
if (number_of_registers > 1)
166+
{
167+
SWSS_LOG_ERROR("Multiple register reads are not supported, num_of_registers: %d\n", number_of_registers);
168+
return SAI_STATUS_FAILURE;
169+
}
170+
171+
ipcMutex.lock();
172+
173+
sprintf(cmd, "mdio 0x%x 0x%x 0x%x\n", mdio_addr, reg_addr, *data);
174+
rc = syncd_mdio_ipc_command(cmd, resp);
175+
if (rc == 0)
176+
{
177+
rc = SAI_STATUS_SUCCESS;
178+
}
179+
else
180+
{
181+
SWSS_LOG_ERROR("syncd_mdio_ipc_command returns : %d\n", rc);
182+
}
183+
184+
ipcMutex.unlock();
185+
return rc;
186+
}
187+
188+
/* Function to read data using clause 22 from MDIO interface */
189+
sai_status_t mdio_read_cl22(uint64_t platform_context, uint32_t mdio_addr, uint32_t reg_addr,
190+
uint32_t number_of_registers, uint32_t *data)
191+
{
192+
// SWSS_LOG_ENTER(); // disabled
193+
194+
int rc = SAI_STATUS_FAILURE;
195+
char cmd[SYNCD_IPC_BUFF_SIZE], resp[SYNCD_IPC_BUFF_SIZE];
196+
197+
if (number_of_registers > 1)
198+
{
199+
SWSS_LOG_ERROR("Multiple register reads are not supported, num_of_registers: %d\n", number_of_registers);
200+
return SAI_STATUS_FAILURE;
201+
}
202+
203+
ipcMutex.lock();
204+
205+
sprintf(cmd, "mdio-cl22 0x%x 0x%x\n", mdio_addr, reg_addr);
206+
rc = syncd_mdio_ipc_command(cmd, resp);
207+
if (rc == 0)
208+
{
209+
*data = (uint32_t)strtoul(strchrnul(resp, ' ') + 1, NULL, 0);
210+
rc = SAI_STATUS_SUCCESS;
211+
}
212+
else
213+
{
214+
SWSS_LOG_ERROR("syncd_mdio_ipc_command returns : %d\n", rc);
215+
}
216+
217+
ipcMutex.unlock();
218+
return rc;
219+
}
220+
221+
/* Function to write data using clause 22 to MDIO interface */
222+
sai_status_t mdio_write_cl22(uint64_t platform_context, uint32_t mdio_addr, uint32_t reg_addr,
223+
uint32_t number_of_registers, const uint32_t *data)
224+
{
225+
// SWSS_LOG_ENTER(); // disabled
226+
227+
int rc = SAI_STATUS_FAILURE;
228+
char cmd[SYNCD_IPC_BUFF_SIZE], resp[SYNCD_IPC_BUFF_SIZE];
229+
230+
if (number_of_registers > 1)
231+
{
232+
SWSS_LOG_ERROR("Multiple register reads are not supported, num_of_registers: %d\n", number_of_registers);
233+
return SAI_STATUS_FAILURE;
234+
}
235+
236+
ipcMutex.lock();
237+
238+
sprintf(cmd, "mdio-cl22 0x%x 0x%x 0x%x\n", mdio_addr, reg_addr, *data);
239+
rc = syncd_mdio_ipc_command(cmd, resp);
240+
if (rc == 0)
241+
{
242+
rc = SAI_STATUS_SUCCESS;
243+
}
244+
else
245+
{
246+
SWSS_LOG_ERROR("syncd_mdio_ipc_command returns : %d\n", rc);
247+
}
248+
249+
ipcMutex.unlock();
250+
return rc;
251+
}

0 commit comments

Comments
 (0)