1414#include <string.h>
1515#include <err.h>
1616#include <sys/socket.h>
17+ #include <poll.h>
1718
1819#include "mctp.h"
1920#include "mctp-util.h"
@@ -28,10 +29,11 @@ static const uint8_t MCTP_TYPE_VENDOR_PCIE = 0x7e;
2829
2930/* lladdrlen != -1 to ignore ifindex/lladdr */
3031static int mctp_req (unsigned int net , mctp_eid_t eid , unsigned int ifindex ,
31- uint8_t * lladdr , int lladdrlen , uint8_t * data , size_t len )
32+ uint8_t * lladdr , int lladdrlen , uint8_t * data , size_t len ,
33+ int8_t type , unsigned int timeout )
3234{
3335 struct sockaddr_mctp_ext addr ;
34- unsigned char * payload , * buf ;
36+ unsigned char * buf ;
3537 socklen_t addrlen ;
3638 int rc , sd , val ;
3739 size_t i , buf_len ;
@@ -45,24 +47,10 @@ static int mctp_req(unsigned int net, mctp_eid_t eid, unsigned int ifindex,
4547 addr .smctp_base .smctp_family = AF_MCTP ;
4648 addr .smctp_base .smctp_network = net ;
4749 addr .smctp_base .smctp_addr .s_addr = eid ;
48- addr .smctp_base .smctp_type = MCTP_TYPE_VENDOR_PCIE ;
50+ addr .smctp_base .smctp_type = type ;
4951 addr .smctp_base .smctp_tag = MCTP_TAG_OWNER ;
50- printf ("req: sending to (net %d, eid %d), type 0x%x\n" , net , eid ,
51- addr .smctp_base .smctp_type );
52-
53- buf_len = len + sizeof (VENDOR_TYPE_ECHO );
54- buf = malloc (buf_len );
55- if (!buf )
56- err (EXIT_FAILURE , "malloc" );
57- memcpy (buf , VENDOR_TYPE_ECHO , sizeof (VENDOR_TYPE_ECHO ));
58- payload = & buf [sizeof (VENDOR_TYPE_ECHO )];
59-
60- if (data ) {
61- memcpy (payload , data , len );
62- } else {
63- for (i = 0 ; i < len ; i ++ )
64- payload [i ] = i & 0xff ;
65- }
52+ printf ("req: sending to (net %d, eid %d), type 0x%02x, len %zu\n" , net ,
53+ eid , type , len );
6654
6755 /* extended addressing */
6856 if (lladdrlen != -1 ) {
@@ -82,9 +70,23 @@ static int mctp_req(unsigned int net, mctp_eid_t eid, unsigned int ifindex,
8270 }
8371
8472 /* send data */
85- rc = sendto (sd , buf , buf_len , 0 , (struct sockaddr * )& addr , addrlen );
86- if (rc != (int )buf_len )
87- err (EXIT_FAILURE , "sendto(%zd)" , buf_len );
73+ rc = sendto (sd , data , len , 0 , (struct sockaddr * )& addr , addrlen );
74+ if (rc != (int )len )
75+ err (EXIT_FAILURE , "sendto(%zd)" , len );
76+
77+ struct pollfd pfd = { .fd = sd , .events = POLLIN };
78+ if (poll (& pfd , 1 , timeout ) <= 0 ) {
79+ return -1 ;
80+ }
81+
82+ rc = recvfrom (sd , NULL , 0 , MSG_PEEK | MSG_TRUNC , NULL , 0 );
83+ if (rc < 0 )
84+ err (EXIT_FAILURE , "recvfrom" );
85+ buf_len = (size_t )rc ;
86+
87+ buf = malloc (buf_len );
88+ if (!buf )
89+ err (EXIT_FAILURE , "malloc" );
8890
8991 /* receive response */
9092 addrlen = sizeof (addr );
@@ -103,26 +105,46 @@ static int mctp_req(unsigned int net, mctp_eid_t eid, unsigned int ifindex,
103105 sizeof (struct sockaddr_mctp_ext ),
104106 sizeof (struct sockaddr_mctp ));
105107
106- printf ("req : message from (net %d, eid %d) type 0x%x len %zd\n" ,
108+ printf ("rsp : message from (net %d, eid %d) type 0x%02x len %zd\n" ,
107109 addr .smctp_base .smctp_network , addr .smctp_base .smctp_addr .s_addr ,
108- addr .smctp_base .smctp_type , len );
110+ addr .smctp_base .smctp_type , buf_len );
109111 if (addrlen == sizeof (struct sockaddr_mctp_ext )) {
110112 printf (" ext ifindex %d ha[0]=0x%02x len %hhu\n" ,
111113 addr .smctp_ifindex , addr .smctp_haddr [0 ],
112114 addr .smctp_halen );
113115 }
114116
115- if (memcmp (buf , VENDOR_TYPE_ECHO , sizeof (VENDOR_TYPE_ECHO )) != 0 ) {
116- errx (EXIT_FAILURE , "unexpected vendor ID" );
117+ printf ("data:" );
118+ for (i = 0 ; i < buf_len ; i ++ ) {
119+ if (i % 16 == 0 )
120+ printf ("\n%04X\t" , i );
121+ printf ("0x%02x " , buf [i ]);
117122 }
123+ printf ("\n" );
124+
125+ if (type == MCTP_TYPE_VENDOR_PCIE &&
126+ !memcmp (data , VENDOR_TYPE_ECHO , sizeof (VENDOR_TYPE_ECHO ))) {
127+ if (buf_len >= sizeof (VENDOR_TYPE_ECHO ) &&
128+ memcmp (buf , VENDOR_TYPE_ECHO , sizeof (VENDOR_TYPE_ECHO ))) {
129+ errx (EXIT_FAILURE , "unexpected vendor ID" );
130+ }
118131
119- for (i = 0 ; i < len ; i ++ ) {
120- uint8_t exp = data ? data [i ] : i & 0xff ;
121- if (payload [i ] != exp )
132+ if (len != buf_len ) {
122133 errx (EXIT_FAILURE ,
123- "payload mismatch at byte 0x%zx; "
124- "sent 0x%02x, received 0x%02x" ,
125- i , exp , buf [i ]);
134+ "unmatched payload length, "
135+ "sent %zd bytes, but received %zd bytes" ,
136+ len - sizeof (VENDOR_TYPE_ECHO ),
137+ buf_len - sizeof (VENDOR_TYPE_ECHO ));
138+ }
139+
140+ for (i = sizeof (VENDOR_TYPE_ECHO ); i < len ; i ++ ) {
141+ if (buf [i ] != data [i ])
142+ errx (EXIT_FAILURE ,
143+ "payload mismatch at byte 0x%zx; "
144+ "sent 0x%02x, but received 0x%02x" ,
145+ i - sizeof (VENDOR_TYPE_ECHO ), data [i ],
146+ buf [i ]);
147+ }
126148 }
127149
128150 return 0 ;
@@ -131,21 +153,29 @@ static int mctp_req(unsigned int net, mctp_eid_t eid, unsigned int ifindex,
131153static void usage (void )
132154{
133155 fprintf (stderr ,
134- "mctp-req [eid <eid>] [net <net>] [ifindex <ifindex> lladdr <hwaddr>] [len <len>]\n" );
156+ "mctp-req [eid <eid>] [net <net>] [ifindex <ifindex> lladdr <hwaddr>]"
157+ " [timeout <ms>] [type <type>] [len <len>] [data <data>]\n" );
135158 fprintf (stderr , "default eid %d net %d len %zd\n" , DEFAULT_EID ,
136159 DEFAULT_NET , DEFAULT_LEN );
160+ fprintf (stderr ,
161+ "default to send <data> as payload of code construct echo command if"
162+ " type is not specified" );
163+ fprintf (stderr , "<data> is colon separated hex bytes, e.g. cc:de:f0" );
137164}
138165
139166int main (int argc , char * * argv )
140167{
141- uint8_t * data , lladdr [MAX_ADDR_LEN ];
168+ uint8_t * data = NULL , * buf , lladdr [MAX_ADDR_LEN ];
142169 int lladdrlen = -1 , datalen = -1 ;
143170 unsigned int net = DEFAULT_NET ;
144171 mctp_eid_t eid = DEFAULT_EID ;
145172 size_t len = DEFAULT_LEN , sz ;
146173 char * endp , * optname , * optval ;
147174 unsigned int tmp , ifindex ;
175+ uint8_t type = MCTP_TYPE_VENDOR_PCIE ;
176+ unsigned int timeout = 1000 ;
148177 bool valid_parse ;
178+ bool echo_req = true;
149179 int i ;
150180
151181 if (!(argc % 2 )) {
@@ -174,16 +204,25 @@ int main(int argc, char **argv)
174204 net = tmp ;
175205 } else if (!strcmp (optname , "ifindex" )) {
176206 ifindex = tmp ;
207+ } else if (!strcmp (optname , "timeout" )) {
208+ timeout = tmp ;
177209 } else if (!strcmp (optname , "len" )) {
178210 if (tmp > 64 * 1024 )
179211 errx (EXIT_FAILURE , "Bad len" );
180212 len = tmp ;
213+ } else if (!strcmp (optname , "type" )) {
214+ if (tmp > 0xff )
215+ errx (EXIT_FAILURE , "Bad type" );
216+ type = tmp ;
217+ echo_req = false;
181218 } else if (!strcmp (optname , "data" )) {
182219 sz = (strlen (optval ) + 2 ) / 3 ;
183- data = malloc (sz );
220+ data = malloc (sz + sizeof ( VENDOR_TYPE_ECHO ) );
184221 if (!data )
185222 err (EXIT_FAILURE , "malloc" );
186- if (parse_hex_addr (optval , data , & sz )) {
223+ if (parse_hex_addr (optval ,
224+ data + sizeof (VENDOR_TYPE_ECHO ),
225+ & sz )) {
187226 errx (EXIT_FAILURE , "Bad data" );
188227 }
189228 datalen = sz ;
@@ -205,8 +244,25 @@ int main(int argc, char **argv)
205244 }
206245 }
207246
208- if (data )
247+ if (data ) {
209248 len = datalen ;
249+ } else {
250+ data = malloc (len + sizeof (VENDOR_TYPE_ECHO ));
251+ if (!data )
252+ err (EXIT_FAILURE , "malloc" );
253+ buf = data + sizeof (VENDOR_TYPE_ECHO );
254+ for (i = 0 ; i < len ; i ++ )
255+ * buf = i & 0xff ;
256+ }
257+
258+ if (echo_req ) {
259+ memcpy (data , VENDOR_TYPE_ECHO , sizeof (VENDOR_TYPE_ECHO ));
260+ buf = data ;
261+ len += sizeof (VENDOR_TYPE_ECHO );
262+ } else {
263+ buf = data + sizeof (VENDOR_TYPE_ECHO );
264+ }
210265
211- return mctp_req (net , eid , ifindex , lladdr , lladdrlen , data , len );
266+ return mctp_req (net , eid , ifindex , lladdr , lladdrlen , buf , len , type ,
267+ timeout );
212268}
0 commit comments