+ /* Sequence number */
+ if (tlen < 2)
+ goto tooshort;
+ ND_PRINT("\n\t Sequence Number %u", GET_BE_U_2(tptr));
+ tlen -= 2;
+ tptr += 2;
+
+ /* TLVs */
+ while (tlen > 0) {
+ ptr.slow_oam_tlv_header = (const struct slow_oam_tlv_header_t *)tptr;
+ if (tlen < sizeof(*ptr.slow_oam_tlv_header))
+ goto tooshort;
+ type = GET_U_1(ptr.slow_oam_tlv_header->type);
+ length = GET_U_1(ptr.slow_oam_tlv_header->length);
+ ND_PRINT("\n\t %s Link Event Type (%u), length %u",
+ tok2str(slow_oam_link_event_values, "Reserved",
+ type),
+ type,
+ length);
+
+ if (type == SLOW_OAM_INFO_TYPE_END_OF_TLV) {
+ /*
+ * As IEEE Std 802.3-2015 says for the End of TLV Marker,
+ * "(the length and value of the Type 0x00 TLV can be ignored)".
+ */
+ return;
+ }
+
+ /* length includes the type and length fields */
+ if (length < sizeof(struct slow_oam_tlv_header_t)) {
+ ND_PRINT("\n\t ERROR: illegal length - should be >= %zu",
+ sizeof(struct slow_oam_tlv_header_t));
+ return;
+ }
+
+ if (tlen < length)
+ goto tooshort;
+ ND_TCHECK_LEN(tptr, length);
+
+ hexdump = FALSE;
+ switch (type) {
+ case SLOW_OAM_LINK_EVENT_ERR_SYM_PER: /* identical format - fall through */
+ case SLOW_OAM_LINK_EVENT_ERR_FRM:
+ case SLOW_OAM_LINK_EVENT_ERR_FRM_PER:
+ case SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM:
+ tlv.slow_oam_link_event = (const struct slow_oam_link_event_t *)tptr;
+
+ if (GET_U_1(tlv.slow_oam_link_event->event_length) !=
+ sizeof(struct slow_oam_link_event_t)) {
+ ND_PRINT("\n\t ERROR: illegal length - should be %zu",
+ sizeof(struct slow_oam_link_event_t));
+ hexdump = TRUE;
+ goto badlength_event_notif;
+ }
+
+ ND_PRINT("\n\t Timestamp %u ms, Errored Window %" PRIu64
+ "\n\t Errored Threshold %" PRIu64
+ "\n\t Errors %" PRIu64
+ "\n\t Error Running Total %" PRIu64
+ "\n\t Event Running Total %u",
+ GET_BE_U_2(tlv.slow_oam_link_event->time_stamp)*100,
+ GET_BE_U_8(tlv.slow_oam_link_event->window),
+ GET_BE_U_8(tlv.slow_oam_link_event->threshold),
+ GET_BE_U_8(tlv.slow_oam_link_event->errors),
+ GET_BE_U_8(tlv.slow_oam_link_event->errors_running_total),
+ GET_BE_U_4(tlv.slow_oam_link_event->event_running_total));
+ break;
+
+ case SLOW_OAM_LINK_EVENT_ORG_SPECIFIC:
+ hexdump = TRUE;
+ break;
+
+ default:
+ hexdump = TRUE;
+ break;
+ }
+
+ badlength_event_notif:
+ /* do we also want to see a hex dump ? */
+ if (ndo->ndo_vflag > 1 || hexdump==TRUE) {
+ print_unknown_data(ndo, tptr, "\n\t ",
+ length);
+ }
+
+ tlen -= length;
+ tptr += length;
+ }
+ break;
+
+ case SLOW_OAM_CODE_LOOPBACK_CTRL:
+ tlv.slow_oam_loopbackctrl = (const struct slow_oam_loopbackctrl_t *)tptr;
+ if (tlen < sizeof(*tlv.slow_oam_loopbackctrl))
+ goto tooshort;
+ command = GET_U_1(tlv.slow_oam_loopbackctrl->command);
+ ND_PRINT("\n\t Command %s (%u)",
+ tok2str(slow_oam_loopbackctrl_cmd_values,
+ "Unknown",
+ command),
+ command);
+ tptr ++;
+ tlen --;
+ break;
+
+ /*
+ * FIXME those are the defined codes that lack a decoder
+ * you are welcome to contribute code ;-)
+ */