hwtstamp_config.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /* Test program for SIOC{G,S}HWTSTAMP
  2. * Copyright 2013 Solarflare Communications
  3. * Author: Ben Hutchings
  4. */
  5. #include <errno.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/socket.h>
  10. #include <sys/ioctl.h>
  11. #include <linux/if.h>
  12. #include <linux/net_tstamp.h>
  13. #include <linux/sockios.h>
  14. static int
  15. lookup_value(const char **names, int size, const char *name)
  16. {
  17. int value;
  18. for (value = 0; value < size; value++)
  19. if (names[value] && strcasecmp(names[value], name) == 0)
  20. return value;
  21. return -1;
  22. }
  23. static const char *
  24. lookup_name(const char **names, int size, int value)
  25. {
  26. return (value >= 0 && value < size) ? names[value] : NULL;
  27. }
  28. static void list_names(FILE *f, const char **names, int size)
  29. {
  30. int value;
  31. for (value = 0; value < size; value++)
  32. if (names[value])
  33. fprintf(f, " %s\n", names[value]);
  34. }
  35. static const char *tx_types[] = {
  36. #define TX_TYPE(name) [HWTSTAMP_TX_ ## name] = #name
  37. TX_TYPE(OFF),
  38. TX_TYPE(ON),
  39. TX_TYPE(ONESTEP_SYNC)
  40. #undef TX_TYPE
  41. };
  42. #define N_TX_TYPES ((int)(sizeof(tx_types) / sizeof(tx_types[0])))
  43. static const char *rx_filters[] = {
  44. #define RX_FILTER(name) [HWTSTAMP_FILTER_ ## name] = #name
  45. RX_FILTER(NONE),
  46. RX_FILTER(ALL),
  47. RX_FILTER(SOME),
  48. RX_FILTER(PTP_V1_L4_EVENT),
  49. RX_FILTER(PTP_V1_L4_SYNC),
  50. RX_FILTER(PTP_V1_L4_DELAY_REQ),
  51. RX_FILTER(PTP_V2_L4_EVENT),
  52. RX_FILTER(PTP_V2_L4_SYNC),
  53. RX_FILTER(PTP_V2_L4_DELAY_REQ),
  54. RX_FILTER(PTP_V2_L2_EVENT),
  55. RX_FILTER(PTP_V2_L2_SYNC),
  56. RX_FILTER(PTP_V2_L2_DELAY_REQ),
  57. RX_FILTER(PTP_V2_EVENT),
  58. RX_FILTER(PTP_V2_SYNC),
  59. RX_FILTER(PTP_V2_DELAY_REQ),
  60. #undef RX_FILTER
  61. };
  62. #define N_RX_FILTERS ((int)(sizeof(rx_filters) / sizeof(rx_filters[0])))
  63. static void usage(void)
  64. {
  65. fputs("Usage: hwtstamp_config if_name [tx_type rx_filter]\n"
  66. "tx_type is any of (case-insensitive):\n",
  67. stderr);
  68. list_names(stderr, tx_types, N_TX_TYPES);
  69. fputs("rx_filter is any of (case-insensitive):\n", stderr);
  70. list_names(stderr, rx_filters, N_RX_FILTERS);
  71. }
  72. int main(int argc, char **argv)
  73. {
  74. struct ifreq ifr;
  75. struct hwtstamp_config config;
  76. const char *name;
  77. int sock;
  78. if ((argc != 2 && argc != 4) || (strlen(argv[1]) >= IFNAMSIZ)) {
  79. usage();
  80. return 2;
  81. }
  82. if (argc == 4) {
  83. config.flags = 0;
  84. config.tx_type = lookup_value(tx_types, N_TX_TYPES, argv[2]);
  85. config.rx_filter = lookup_value(rx_filters, N_RX_FILTERS, argv[3]);
  86. if (config.tx_type < 0 || config.rx_filter < 0) {
  87. usage();
  88. return 2;
  89. }
  90. }
  91. sock = socket(AF_INET, SOCK_DGRAM, 0);
  92. if (sock < 0) {
  93. perror("socket");
  94. return 1;
  95. }
  96. strcpy(ifr.ifr_name, argv[1]);
  97. ifr.ifr_data = (caddr_t)&config;
  98. if (ioctl(sock, (argc == 2) ? SIOCGHWTSTAMP : SIOCSHWTSTAMP, &ifr)) {
  99. perror("ioctl");
  100. return 1;
  101. }
  102. printf("flags = %#x\n", config.flags);
  103. name = lookup_name(tx_types, N_TX_TYPES, config.tx_type);
  104. if (name)
  105. printf("tx_type = %s\n", name);
  106. else
  107. printf("tx_type = %d\n", config.tx_type);
  108. name = lookup_name(rx_filters, N_RX_FILTERS, config.rx_filter);
  109. if (name)
  110. printf("rx_filter = %s\n", name);
  111. else
  112. printf("rx_filter = %d\n", config.rx_filter);
  113. return 0;
  114. }