print-medsa.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that: (1) source code distributions
  7. * retain the above copyright notice and this paragraph in its entirety, (2)
  8. * distributions including binary code include the above copyright notice and
  9. * this paragraph in its entirety in the documentation or other materials
  10. * provided with the distribution, and (3) all advertising materials mentioning
  11. * features or use of this software display the following acknowledgement:
  12. * ``This product includes software developed by the University of California,
  13. * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  14. * the University nor the names of its contributors may be used to endorse
  15. * or promote products derived from this software without specific prior
  16. * written permission.
  17. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  18. * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  19. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  20. */
  21. /* \summary: Marvell Extended Distributed Switch Architecture (MEDSA) printer */
  22. #ifdef HAVE_CONFIG_H
  23. #include "config.h"
  24. #endif
  25. #include <netdissect-stdinc.h>
  26. #include "netdissect.h"
  27. #include "ether.h"
  28. #include "ethertype.h"
  29. #include "addrtoname.h"
  30. #include "extract.h"
  31. static const char tstr[] = "[|MEDSA]";
  32. /*
  33. * Marvell Extended Distributed Switch Archiecture.
  34. *
  35. * A Marvell propriatary header used for passing packets to/from
  36. * specific ports of a switch. There is no open specification of this
  37. * header, but is documented in the Marvell Switch data sheets. For
  38. * background, see:
  39. *
  40. * https://lwn.net/Articles/302333/
  41. */
  42. struct medsa_pkthdr {
  43. u_char bytes[6];
  44. u_short ether_type;
  45. };
  46. /* Bytes 0 and 1 are reserved and should contain 0 */
  47. #define TAG(medsa) (medsa->bytes[2] >> 6)
  48. #define TAG_TO_CPU 0
  49. #define TAG_FROM_CPU 1
  50. #define TAG_FORWARD 3
  51. #define SRC_TAG(medsa) ((medsa->bytes[2] >> 5) & 0x01)
  52. #define SRC_DEV(medsa) (medsa->bytes[2] & 0x1f)
  53. #define SRC_PORT(medsa) ((medsa->bytes[3] >> 3) & 0x01f)
  54. #define TRUNK(medsa) ((medsa->bytes[3] >> 2) & 0x01)
  55. #define CODE(medsa) ((medsa->bytes[3] & 0x06) | \
  56. ((medsa->bytes[4] >> 4) & 0x01))
  57. #define CODE_BDPU 0
  58. #define CODE_IGMP_MLD 2
  59. #define CODE_ARP_MIRROR 4
  60. #define CFI(medsa) (medsa->bytes[3] & 0x01)
  61. #define PRI(medsa) (medsa->bytes[4] >> 5)
  62. #define VID(medsa) (((u_short)(medsa->bytes[4] & 0xf) << 8 | \
  63. medsa->bytes[5]))
  64. static const struct tok tag_values[] = {
  65. { TAG_TO_CPU, "To_CPU" },
  66. { TAG_FROM_CPU, "From_CPU" },
  67. { TAG_FORWARD, "Forward" },
  68. { 0, NULL },
  69. };
  70. static const struct tok code_values[] = {
  71. { CODE_BDPU, "BDPU" },
  72. { CODE_IGMP_MLD, "IGMP/MLD" },
  73. { CODE_ARP_MIRROR, "APR_Mirror" },
  74. { 0, NULL },
  75. };
  76. static void
  77. medsa_print_full(netdissect_options *ndo,
  78. const struct medsa_pkthdr *medsa,
  79. u_int caplen)
  80. {
  81. u_char tag = TAG(medsa);
  82. ND_PRINT((ndo, "%s",
  83. tok2str(tag_values, "Unknown (%u)", tag)));
  84. switch (tag) {
  85. case TAG_TO_CPU:
  86. ND_PRINT((ndo, ", %stagged", SRC_TAG(medsa) ? "" : "un"));
  87. ND_PRINT((ndo, ", dev.port:vlan %d.%d:%d",
  88. SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
  89. ND_PRINT((ndo, ", %s",
  90. tok2str(code_values, "Unknown (%u)", CODE(medsa))));
  91. if (CFI(medsa))
  92. ND_PRINT((ndo, ", CFI"));
  93. ND_PRINT((ndo, ", pri %d: ", PRI(medsa)));
  94. break;
  95. case TAG_FROM_CPU:
  96. ND_PRINT((ndo, ", %stagged", SRC_TAG(medsa) ? "" : "un"));
  97. ND_PRINT((ndo, ", dev.port:vlan %d.%d:%d",
  98. SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
  99. if (CFI(medsa))
  100. ND_PRINT((ndo, ", CFI"));
  101. ND_PRINT((ndo, ", pri %d: ", PRI(medsa)));
  102. break;
  103. case TAG_FORWARD:
  104. ND_PRINT((ndo, ", %stagged", SRC_TAG(medsa) ? "" : "un"));
  105. if (TRUNK(medsa))
  106. ND_PRINT((ndo, ", dev.trunk:vlan %d.%d:%d",
  107. SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
  108. else
  109. ND_PRINT((ndo, ", dev.port:vlan %d.%d:%d",
  110. SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
  111. if (CFI(medsa))
  112. ND_PRINT((ndo, ", CFI"));
  113. ND_PRINT((ndo, ", pri %d: ", PRI(medsa)));
  114. break;
  115. default:
  116. ND_DEFAULTPRINT((const u_char *)medsa, caplen);
  117. return;
  118. }
  119. }
  120. void
  121. medsa_print(netdissect_options *ndo,
  122. const u_char *bp, u_int length, u_int caplen,
  123. const struct lladdr_info *src, const struct lladdr_info *dst)
  124. {
  125. const struct medsa_pkthdr *medsa;
  126. u_short ether_type;
  127. medsa = (const struct medsa_pkthdr *)bp;
  128. ND_TCHECK(*medsa);
  129. if (!ndo->ndo_eflag)
  130. ND_PRINT((ndo, "MEDSA %d.%d:%d: ",
  131. SRC_DEV(medsa), SRC_PORT(medsa), VID(medsa)));
  132. else
  133. medsa_print_full(ndo, medsa, caplen);
  134. bp += 8;
  135. length -= 8;
  136. caplen -= 8;
  137. ether_type = EXTRACT_16BITS(&medsa->ether_type);
  138. if (ether_type <= ETHERMTU) {
  139. /* Try to print the LLC-layer header & higher layers */
  140. if (llc_print(ndo, bp, length, caplen, src, dst) < 0) {
  141. /* packet type not known, print raw packet */
  142. if (!ndo->ndo_suppress_default_print)
  143. ND_DEFAULTPRINT(bp, caplen);
  144. }
  145. } else {
  146. if (ndo->ndo_eflag)
  147. ND_PRINT((ndo, "ethertype %s (0x%04x) ",
  148. tok2str(ethertype_values, "Unknown",
  149. ether_type),
  150. ether_type));
  151. if (ethertype_print(ndo, ether_type, bp, length, caplen, src, dst) == 0) {
  152. /* ether_type not known, print raw packet */
  153. if (!ndo->ndo_eflag)
  154. ND_PRINT((ndo, "ethertype %s (0x%04x) ",
  155. tok2str(ethertype_values, "Unknown",
  156. ether_type),
  157. ether_type));
  158. if (!ndo->ndo_suppress_default_print)
  159. ND_DEFAULTPRINT(bp, caplen);
  160. }
  161. }
  162. return;
  163. trunc:
  164. ND_PRINT((ndo, "%s", tstr));
  165. }
  166. /*
  167. * Local Variables:
  168. * c-style: bsd
  169. * End:
  170. */