From 2ab5a2d155148798b2db13e63c0a01081b932b56 Mon Sep 17 00:00:00 2001 From: Emanuele Di Pascale Date: Wed, 14 Nov 2018 15:12:15 +0100 Subject: [PATCH] isisd: implement 'max-area-addresses-mismatch' notification Note that the original IETF YANG model also included a requirement to throttle such notifications so that they would not be sent more often than once every 5 seconds. I did not implement any throttling mechanism yet, mostly because I am not sure whether this limit should apply to the entire isis daemon, to each area, to each neighbor etc. Signed-off-by: Emanuele Di Pascale --- isisd/isis_northbound.c | 26 ++++++++++++++++++++++++++ isisd/isis_pdu.c | 12 ++++++++++++ isisd/isisd.h | 3 +++ 3 files changed, 41 insertions(+) diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c index c112c64ca1..920f3726a1 100644 --- a/isisd/isis_northbound.c +++ b/isisd/isis_northbound.c @@ -2588,6 +2588,32 @@ void isis_notif_lsp_exceed_max(const struct isis_area *area, const char *lsp_id) nb_notification_send(xpath, arguments); } +/* + * XPath: + * /frr-isisd:max-area-addresses-mismatch + */ +void isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit, + uint8_t max_area_addrs, + const char *raw_pdu) +{ + const char *xpath = "/frr-isisd:max-area-addresses-mismatch"; + struct list *arguments = yang_data_list_new(); + char xpath_arg[XPATH_MAXLEN]; + struct yang_data *data; + struct isis_area *area = circuit->area; + + notif_prep_instance_hdr(xpath, area, "default", arguments); + notif_prepr_iface_hdr(xpath, circuit, arguments); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/max-area-addresses", xpath); + data = yang_data_new_uint8(xpath_arg, max_area_addrs); + listnode_add(arguments, data); + snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath); + data = yang_data_new(xpath_arg, raw_pdu); + listnode_add(arguments, data); + + nb_notification_send(xpath, arguments); +} + /* clang-format off */ const struct frr_yang_module_info frr_isisd_info = { .name = "frr-isisd", diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index 2347a15475..fc8fe31d52 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -1423,6 +1423,12 @@ static int pdu_size(uint8_t pdu_type, uint8_t *size) int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) { int retval = ISIS_OK; + size_t pdu_start = stream_get_getp(circuit->rcv_stream); + size_t pdu_end = stream_get_endp(circuit->rcv_stream); + char raw_pdu[pdu_end - pdu_start]; + + stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start, + pdu_end - pdu_start); /* Verify that at least the 8 bytes fixed header have been received */ if (stream_get_endp(circuit->rcv_stream) < ISIS_FIXED_HDR_LEN) { @@ -1437,6 +1443,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) uint8_t pdu_type = stream_getc(circuit->rcv_stream) & 0x1f; /* bits 6-8 are reserved */ uint8_t version2 = stream_getc(circuit->rcv_stream); + stream_forward_getp(circuit->rcv_stream, 1); /* reserved */ uint8_t max_area_addrs = stream_getc(circuit->rcv_stream); @@ -1509,6 +1516,11 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) "maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %" PRIu8 " while the parameter for this IS is %u", max_area_addrs, isis->max_area_addrs); +#ifndef FABRICD + /* send northbound notification */ + isis_notif_max_area_addr_mismatch(circuit, max_area_addrs, + raw_pdu); +#endif /* ifndef FABRICD */ return ISIS_ERROR; } diff --git a/isisd/isisd.h b/isisd/isisd.h index 6f32dbdd58..d91e8cd543 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -231,6 +231,9 @@ extern void isis_notif_corrupted_lsp(const struct isis_area *area, const char *lsp_id); /* currently unused */ extern void isis_notif_lsp_exceed_max(const struct isis_area *area, const char *lsp_id); +extern void +isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit, + uint8_t max_area_addrs, const char *raw_pdu); /* Master of threads. */ extern struct thread_master *master; -- 2.39.5