Hi Ferruh, Thank you for the comments.
My answers are inlined. Best regards, Ivan 17.06.2020 19:45, Ferruh Yigit пишет: > On 6/15/2020 10:01 AM, Ivan Dyukov wrote: >> This commit add function which treat link status structure >> and format it to text representation. > If I am following correctly, the initial need was to escape from speed checks > everytime loging link information caused by this new 'unknown' speed. > > And later suggestion was to have a pre-formatted text for link logging. Correct. > > This patch brings additional link status printing/formatting capability with > custom format string support and with new format specifiers for link (like, > '%D' > link duplex state), > although this is nice work and thanks for it, I am not sure this complexity > and > two new APIs are really needed. Yep. > For me only 'rte_eth_link_format()' without custom format support looks good > enough but I won't object if the concensus is to have them. > I am aware there are multiple applications you are updating logging slightly > different which requires this flexibility but what happens if they use same > pre-formatted text, is that difference really required or happened by time > based > on developers taste? I have changed only few applications but I have plan to change all dpdk examples. Even in those few apps, we have various link status logging text. e.g app/test-pmd/config.c @@ -600,10 +600,9 @@ port_infos_display(portid_t port_id) } else printf("\nmemory allocation on the socket: %u",port->socket_id); - printf("\nLink status: %s\n", (link.link_status) ? ("up") : ("down")); - printf("Link speed: %u Mbps\n", (unsigned) link.link_speed); - printf("Link duplex: %s\n", (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? - ("full-duplex") : ("half-duplex")); + rte_eth_link_printf("\nLink status: %S\n" + "Link speed: %M Mbps\n" + "Link duplex: %D\n", &link); the status is logged in 3 lines. this is special text layoting and I don't know how it will look in one line. Myabe it will require reformat all screen. I don't want to change screen layoting in this patchset. > I will put some comments below in any case. > >> Signed-off-by: Ivan Dyukov <i.dyu...@samsung.com> > <...> > >> @@ -249,6 +249,9 @@ SRCS-$(CONFIG_RTE_LIBRTE_SECURITY) += test_security.c >> >> SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec.c test_ipsec_perf.c >> SRCS-$(CONFIG_RTE_LIBRTE_IPSEC) += test_ipsec_sad.c >> + >> +SRCS-$(CONFIG_RTE_LIBRTE_ETHER) += test_ethdev_link.c > +1 to unit test. > > <...> > >> +int >> +rte_eth_link_printf(const char *const fmt, >> + struct rte_eth_link *link) >> +{ >> + char text[200]; >> + int ret; >> + ret = rte_eth_link_format(text, 200, fmt, link); > Will it be paranoid to add "text[199] = 0" to be sure any custom 'fmt' won't > cause any harm? rte_eth_link_format already do that and it must do that. I would prefer to don't hide rte_eth_link_format bugs in rte_eth_link_printf function. > >> + printf("%s", text); > Not sure if the error still should be printed on error case? > Like for example what the code does when fmt="%X"? yep. I'll add 'ret' check. > >> + return ret; >> +} >> + >> +int >> +rte_eth_link_format(char *str, int32_t len, const char *const fmt, >> + struct rte_eth_link *link) > Why not have the 'len' type 'size_t'? Yes, I can change type of the len but internally we have 'int32_t clen = len;' defined below. clen should be signed variable because rte_eth_link_format much more simpler then snprintf. e.g. snprintf may be called with snprintf(buff, 0, "some text %d", val); no errors returned in this case. it returns length of formated string.so internally I use signed clen to detect end of line and avoid uint overflow. rte_eth_link_format with incorrect or short buffer returns error. > >> + int offset = 0; >> + int32_t clen = len; >> + const char *fmt_cur = fmt; >> + double gbits = (double)link->link_speed / 1000.; >> + /* TBD: make it international? */ >> + static const char LINK_DOWN_STR[] = "Link down"; >> + static const char LINK_UP_STR[] = "Link up at "; >> + static const char UNKNOWN_SPEED_STR[] = "Unknown speed"; >> + static const char MBITS_STR[] = "Mbit/s"; >> + static const char GBITS_STR[] = "Gbit/s"; >> + static const char AUTONEG_STR[] = "Autoneg"; >> + static const char FIXED_STR[] = "Fixed"; >> + static const char FDX_STR[] = "FDX"; >> + static const char HDX_STR[] = "HDX"; >> + static const char UNKNOWN_STR[] = "Unknown"; >> + static const char UP_STR[] = "Up"; >> + static const char DOWN_STR[] = "Down"; >> + if (str == NULL || len == 0) >> + return -1; >> + /* default format string, if no fmt is specified */ >> + if (fmt == NULL) { >> + if (link->link_status == ETH_LINK_DOWN) >> + return snprintf(str, (size_t)clen, "%s", LINK_DOWN_STR); >> + >> + offset = snprintf(str, (size_t)clen, "%s", LINK_UP_STR); >> + if (offset < 0 || (clen - offset) <= 0) >> + return -1; >> + clen -= offset; >> + str += offset; >> + if (link->link_speed == ETH_SPEED_NUM_UNKNOWN) { >> + offset = snprintf(str, clen, "%s", >> + UNKNOWN_SPEED_STR); >> + if (offset < 0 || (clen - offset) <= 0) >> + return -1; > better to use 'strlcpy' & 'strlcat', they are easier to use for these kind of > checks. OK > > <...> > >> + /* Formated status */ >> + } else { >> + char c = *fmt_cur; >> + while (c) { >> + if (clen <= 0) >> + return -1; >> + if (c == '%') { >> + c = *++fmt_cur; >> + switch (c) { >> + /* Speed in Mbits/s */ >> + case 'M': >> + if (link->link_speed == >> + ETH_SPEED_NUM_UNKNOWN) >> + offset = snprintf(str, >> + clen, "%s", >> + UNKNOWN_STR); >> + else >> + offset = snprintf(str, >> + clen, "%u", >> + link->link_speed); > Code readiblity is not great here because you hit the 80char limit, this is a > sign that something is wrong like function is already too long. > Can you please try to fix this, like extracting some part of the code to its > own > function or return after end of the 'if' statement which can save one more > level > indentation etc... agree. I'll define one static function and move part of the code to it. It should reduce indent. > > <...> > >> diff --git a/lib/librte_ethdev/rte_ethdev.h b/lib/librte_ethdev/rte_ethdev.h >> index 2090af501..83291e656 100644 >> --- a/lib/librte_ethdev/rte_ethdev.h >> +++ b/lib/librte_ethdev/rte_ethdev.h >> @@ -2295,6 +2295,58 @@ int rte_eth_link_get(uint16_t port_id, struct >> rte_eth_link *link); >> */ >> int rte_eth_link_get_nowait(uint16_t port_id, struct rte_eth_link *link); >> >> + >> +/** >> + * print formated link status to stdout. This function threats all >> + * special values like ETH_SPEED_NUM_UNKNOWN, ETH_LINK_DOWN etc. and convert >> + * them to textual representation. >> + * >> + * @param fmt >> + * Format string which allow to format link status. If NULL is provided >> + * , default formating will be applied. >> + * Following specifiers are available: >> + * - '%M' link speed in Mbits/s >> + * - '%G' link speed in Gbits/s >> + * - '%S' link status. e.g. Up or Down >> + * - '%A' link autonegotiation state >> + * - '%D' link duplex state >> + * @param link >> + * Link status provided by rte_eth_link_get function >> + * @return >> + * - Number of bytes written to stdout. In case of error, -1 is returned. > Does it worth to mention the log still will be printed on error? I'll change the function. It will print nothing on error. > >> + * >> + */ >> +int rte_eth_link_printf(const char *const fmt, >> + struct rte_eth_link *link); >> + >> +/** >> + * Format link status to textual representation. This function threats all >> + * special values like ETH_SPEED_NUM_UNKNOWN, ETH_LINK_DOWN etc. and convert >> + * them to textual representation. >> + * >> + * @param str >> + * A pointer to a string to be filled with textual representation of >> + * device status. >> + * @param len >> + * Length of available memory at 'str' string. >> + * @param fmt >> + * Format string which allow to format link status. If NULL is provided >> + * , default formating will be applied. >> + * Following specifiers are available: >> + * - '%M' link speed in Mbits/s >> + * - '%G' link speed in Gbits/s >> + * - '%S' link status. e.g. Up or Down >> + * - '%A' link autonegotiation state >> + * - '%D' link duplex state >> + * @param link >> + * Link status provided by rte_eth_link_get function >> + * @return >> + * - Number of bytes written to str array. In case of error, -1 is >> returned. >> + * >> + */ >> +int rte_eth_link_format(char *str, int32_t len, const char *const fmt, >> + struct rte_eth_link *eth_link); >> + > These new APIs needs to be experimental by process (__rte_experimental). > > Need the add these APIs to the .map file (rte_ethdev_version.map), so that > they > will be exported in the dynamic library (.so). > >