From: Christian Franke Date: Tue, 10 Nov 2015 17:43:31 +0000 (+0100) Subject: isisd: allow to adjust lsp-mtu X-Git-Tag: frr-2.0-rc1~1018 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=b20ccb3aa94ff96e8d32e5206d8b16fa3b081908;p=mirror%2Ffrr.git isisd: allow to adjust lsp-mtu Signed-off-by: Christian Franke Acked-by: Donald Sharp --- diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 9f597368d4..a49994a78b 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -574,6 +574,29 @@ isis_circuit_update_all_srmflags (struct isis_circuit *circuit, int is_set) } } +size_t +isis_circuit_pdu_size(struct isis_circuit *circuit) +{ + return ISO_MTU(circuit); +} + +void +isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream) +{ + size_t stream_size = isis_circuit_pdu_size(circuit); + + if (!*stream) + { + *stream = stream_new(stream_size); + } + else + { + if (STREAM_SIZE(*stream) != stream_size) + stream_resize(*stream, stream_size); + stream_reset(*stream); + } +} + int isis_circuit_up (struct isis_circuit *circuit) { @@ -588,6 +611,15 @@ isis_circuit_up (struct isis_circuit *circuit) if (circuit->is_passive) return ISIS_OK; + if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit)) + { + zlog_err("Interface MTU %zu on %s is too low to support area lsp mtu %u!", + isis_circuit_pdu_size(circuit), circuit->interface->name, + circuit->area->lsp_mtu); + isis_circuit_down(circuit); + return ISIS_ERROR; + } + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { /* @@ -620,9 +652,6 @@ isis_circuit_up (struct isis_circuit *circuit) circuit->u.bc.adjdb[0] = list_new (); circuit->u.bc.adjdb[1] = list_new (); - if (circuit->area->min_bcast_mtu == 0 || - ISO_MTU (circuit) < circuit->area->min_bcast_mtu) - circuit->area->min_bcast_mtu = ISO_MTU (circuit); /* * ISO 10589 - 8.4.1 Enabling of broadcast circuits */ @@ -684,11 +713,8 @@ isis_circuit_up (struct isis_circuit *circuit) } /* initialize the circuit streams after opening connection */ - if (circuit->rcv_stream == NULL) - circuit->rcv_stream = stream_new (ISO_MTU (circuit)); - - if (circuit->snd_stream == NULL) - circuit->snd_stream = stream_new (ISO_MTU (circuit)); + isis_circuit_stream(circuit, &circuit->rcv_stream); + isis_circuit_stream(circuit, &circuit->snd_stream); #ifdef GNU_LINUX THREAD_READ_ON (master, circuit->t_read, isis_receive, circuit, @@ -1192,6 +1218,7 @@ DEFUN (ip_router_isis, struct isis_circuit *circuit; struct interface *ifp; struct isis_area *area; + int rv; ifp = (struct interface *) vty->index; assert (ifp); @@ -1220,16 +1247,25 @@ DEFUN (ip_router_isis, area = vty->index; circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area); - isis_circuit_if_bind (circuit, ifp); + if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) + { + vty_out(vty, "Couldn't bring up interface, please check log.%s", VTY_NEWLINE); + rv = CMD_WARNING; + } + else + { + isis_circuit_if_bind (circuit, ifp); - circuit->ip_router = 1; - area->ip_circuits++; - circuit_update_nlpids (circuit); + circuit->ip_router = 1; + area->ip_circuits++; + circuit_update_nlpids (circuit); + rv = CMD_SUCCESS; + } vty->node = INTERFACE_NODE; vty->index = ifp; - return CMD_SUCCESS; + return rv; } DEFUN (no_ip_router_isis, @@ -1290,6 +1326,7 @@ DEFUN (ipv6_router_isis, struct isis_circuit *circuit; struct interface *ifp; struct isis_area *area; + int rv; ifp = (struct interface *) vty->index; assert (ifp); @@ -1318,16 +1355,25 @@ DEFUN (ipv6_router_isis, area = vty->index; circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area); - isis_circuit_if_bind (circuit, ifp); + if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP) + { + vty_out(vty, "Couldn't bring up interface, please check log.%s", VTY_NEWLINE); + rv = CMD_WARNING; + } + else + { + isis_circuit_if_bind (circuit, ifp); - circuit->ipv6_router = 1; - area->ipv6_circuits++; - circuit_update_nlpids (circuit); + circuit->ipv6_router = 1; + area->ipv6_circuits++; + circuit_update_nlpids (circuit); + rv = CMD_SUCCESS; + } vty->node = INTERFACE_NODE; vty->index = ifp; - return CMD_SUCCESS; + return rv; } DEFUN (no_ipv6_router_isis, diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index d86fee040e..d883879731 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -164,5 +164,7 @@ void isis_circuit_down (struct isis_circuit *); void circuit_update_nlpids (struct isis_circuit *circuit); void isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty, char detail); +size_t isis_circuit_pdu_size(struct isis_circuit *circuit); +void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream); #endif /* _ZEBRA_ISIS_CIRCUIT_H */ diff --git a/isisd/isis_constants.h b/isisd/isis_constants.h index bb2c4b4061..8b21894e43 100644 --- a/isisd/isis_constants.h +++ b/isisd/isis_constants.h @@ -34,7 +34,6 @@ #define ISO_SAP 0xFE #define INTRADOMAIN_ROUTEING_SELECTOR 0 #define SEQUENCE_MODULUS 4294967296 -#define RECEIVE_LSP_BUFFER_SIZE 1492 /* * implementation specific jitter values diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 452a8a678f..ed4ce25637 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -575,15 +575,16 @@ lsp_new_from_stream_ptr (struct stream *stream, } struct isis_lsp * -lsp_new (u_char * lsp_id, u_int16_t rem_lifetime, u_int32_t seq_num, - u_int8_t lsp_bits, u_int16_t checksum, int level) +lsp_new(struct isis_area *area, u_char * lsp_id, + u_int16_t rem_lifetime, u_int32_t seq_num, + u_int8_t lsp_bits, u_int16_t checksum, int level) { struct isis_lsp *lsp; lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp)); + lsp->area = area; - /* FIXME: Should be minimal mtu? */ - lsp->pdu = stream_new (1500); + lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu); if (LSP_FRAGMENT (lsp_id) == 0) lsp->lspu.frags = list_new (); lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu)); @@ -1131,7 +1132,7 @@ lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0, struct isis_area *area, lsp_clear_data (lsp); return lsp; } - lsp = lsp_new (frag_id, ntohs(lsp0->lsp_header->rem_lifetime), 0, + lsp = lsp_new (area, frag_id, ntohs(lsp0->lsp_header->rem_lifetime), 0, lsp_bits_generate (level, area->overload_bit, area->attached_bit), 0, level); lsp->area = area; @@ -1593,7 +1594,7 @@ lsp_generate (struct isis_area *area, int level) area->lspdb[level - 1]); } rem_lifetime = lsp_rem_lifetime (area, level); - newlsp = lsp_new (lspid, rem_lifetime, seq_num, + newlsp = lsp_new (area, lspid, rem_lifetime, seq_num, area->is_type | area->overload_bit | area->attached_bit, 0, level); newlsp->area = area; @@ -1966,7 +1967,7 @@ lsp_generate_pseudo (struct isis_circuit *circuit, int level) rem_lifetime = lsp_rem_lifetime (circuit->area, level); /* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */ - lsp = lsp_new (lsp_id, rem_lifetime, 1, + lsp = lsp_new (circuit->area, lsp_id, rem_lifetime, 1, circuit->area->is_type | circuit->area->attached_bit, 0, level); lsp->area = circuit->area; @@ -2356,8 +2357,7 @@ lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr, lsp->area = area; lsp->level = ((lsp_hdr->lsp_bits & LSPBIT_IST) == IS_LEVEL_1) ? IS_LEVEL_1 : IS_LEVEL_2; - /* FIXME: Should be minimal mtu? */ - lsp->pdu = stream_new (1500); + lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu); lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu); fill_fixed_hdr (lsp->isis_header, (lsp->level == IS_LEVEL_1) ? L1_LINK_STATE : L2_LINK_STATE); @@ -2479,11 +2479,11 @@ generate_topology_lsps (struct isis_area *area) lspid[ISIS_SYS_ID_LEN - 2] = ((i >> 8) & 0xFF); rem_lifetime = lsp_rem_lifetime (area, IS_LEVEL_1); - lsp = lsp_new (lspid, rem_lifetime, 1, IS_LEVEL_1 | area->overload_bit - | area->attached_bit, 0, 1); + lsp = lsp_new (area, lspid, rem_lifetime, 1, + IS_LEVEL_1 | area->overload_bit | area->attached_bit, + 0, 1); if (!lsp) return; - lsp->area = area; lsp->from_topology = 1; /* Creating LSP data based on topology info. */ diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index 6e7f745d2a..92a5dfe595 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -66,7 +66,8 @@ int lsp_regenerate_schedule (struct isis_area *area, int level, int lsp_generate_pseudo (struct isis_circuit *circuit, int level); int lsp_regenerate_schedule_pseudo (struct isis_circuit *circuit, int level); -struct isis_lsp *lsp_new (u_char * lsp_id, u_int16_t rem_lifetime, +struct isis_lsp *lsp_new (struct isis_area *area, u_char * lsp_id, + u_int16_t rem_lifetime, u_int32_t seq_num, u_int8_t lsp_bits, u_int16_t checksum, int level); struct isis_lsp *lsp_new_from_stream_ptr (struct stream *stream, diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index d9e98f2683..361a90be85 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -1867,9 +1867,9 @@ process_snp (int snp_type, int level, struct isis_circuit *circuit, if (entry->rem_lifetime && entry->checksum && entry->seq_num && memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) { - lsp = lsp_new (entry->lsp_id, ntohs (entry->rem_lifetime), - 0, 0, entry->checksum, level); - lsp->area = circuit->area; + lsp = lsp_new(circuit->area, entry->lsp_id, + ntohs(entry->rem_lifetime), + 0, 0, entry->checksum, level); lsp_insert (lsp, circuit->area->lspdb[level - 1]); ISIS_FLAGS_CLEAR_ALL (lsp->SRMflags); ISIS_SET_FLAG (lsp->SSNflags, circuit); @@ -2093,10 +2093,7 @@ isis_receive (struct thread *thread) circuit = THREAD_ARG (thread); assert (circuit); - if (circuit->rcv_stream == NULL) - circuit->rcv_stream = stream_new (ISO_MTU (circuit)); - else - stream_reset (circuit->rcv_stream); + isis_circuit_stream(circuit, &circuit->rcv_stream); retval = circuit->rx (circuit, ssnpa); circuit->t_read = NULL; @@ -2132,10 +2129,7 @@ isis_receive (struct thread *thread) circuit->t_read = NULL; - if (circuit->rcv_stream == NULL) - circuit->rcv_stream = stream_new (ISO_MTU (circuit)); - else - stream_reset (circuit->rcv_stream); + isis_circuit_stream(circuit, &circuit->rcv_stream); retval = circuit->rx (circuit, ssnpa); @@ -2240,10 +2234,7 @@ send_hello (struct isis_circuit *circuit, int level) return ISIS_WARNING; } - if (!circuit->snd_stream) - circuit->snd_stream = stream_new (ISO_MTU (circuit)); - else - stream_reset (circuit->snd_stream); + isis_circuit_stream(circuit, &circuit->snd_stream); if (circuit->circ_type == CIRCUIT_T_BROADCAST) if (level == IS_LEVEL_1) @@ -2501,10 +2492,7 @@ build_csnp (int level, u_char * start, u_char * stop, struct list *lsps, unsigned long auth_tlv_offset = 0; int retval = ISIS_OK; - if (circuit->snd_stream == NULL) - circuit->snd_stream = stream_new (ISO_MTU (circuit)); - else - stream_reset (circuit->snd_stream); + isis_circuit_stream(circuit, &circuit->snd_stream); if (level == IS_LEVEL_1) fill_fixed_hdr_andstream (&fixed_hdr, L1_COMPLETE_SEQ_NUM, @@ -2828,10 +2816,7 @@ build_psnp (int level, struct isis_circuit *circuit, struct list *lsps) unsigned long auth_tlv_offset = 0; int retval = ISIS_OK; - if (circuit->snd_stream == NULL) - circuit->snd_stream = stream_new (ISO_MTU (circuit)); - else - stream_reset (circuit->snd_stream); + isis_circuit_stream(circuit, &circuit->snd_stream); if (level == IS_LEVEL_1) fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM, @@ -3153,10 +3138,7 @@ ack_lsp (struct isis_link_state_hdr *hdr, struct isis_circuit *circuit, u_int16_t length; struct isis_fixed_hdr fixed_hdr; - if (!circuit->snd_stream) - circuit->snd_stream = stream_new (ISO_MTU (circuit)); - else - stream_reset (circuit->snd_stream); + isis_circuit_stream(circuit, &circuit->snd_stream); // fill_llc_hdr (stream); if (level == IS_LEVEL_1) diff --git a/isisd/isisd.c b/isisd/isisd.c index d786f402a0..ee47f36a83 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -158,13 +158,11 @@ isis_area_create (const char *area_tag) area->oldmetric = 0; area->newmetric = 1; area->lsp_frag_threshold = 90; + area->lsp_mtu = DEFAULT_LSP_MTU; #ifdef TOPOLOGY_GENERATE memcpy (area->topology_baseis, DEFAULT_TOPOLOGY_BASEIS, ISIS_SYS_ID_LEN); #endif /* TOPOLOGY_GENERATE */ - /* FIXME: Think of a better way... */ - area->min_bcast_mtu = 1497; - area->area_tag = strdup (area_tag); listnode_add (isis->area_list, area); area->isis = isis; @@ -1546,6 +1544,76 @@ DEFUN (no_net, return area_clear_net_title (vty, argv[0]); } +static +int area_set_lsp_mtu(struct vty *vty, struct isis_area *area, unsigned int lsp_mtu) +{ + struct isis_circuit *circuit; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) + { + if(lsp_mtu > isis_circuit_pdu_size(circuit)) + { + vty_out(vty, "ISIS area contains circuit %s, which has a maximum PDU size of %zu.%s", + circuit->interface->name, isis_circuit_pdu_size(circuit), + VTY_NEWLINE); + return CMD_ERR_AMBIGUOUS; + } + } + + area->lsp_mtu = lsp_mtu; + lsp_regenerate_schedule(area, IS_LEVEL_1_AND_2, 1); + + return CMD_SUCCESS; +} + +DEFUN (area_lsp_mtu, + area_lsp_mtu_cmd, + "lsp-mtu <128-4352>", + "Configure the maximum size of generated LSPs\n" + "Maximum size of generated LSPs\n") +{ + struct isis_area *area; + + area = vty->index; + if (!area) + { + vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE); + return CMD_ERR_NO_MATCH; + } + + unsigned int lsp_mtu; + + VTY_GET_INTEGER_RANGE("lsp-mtu", lsp_mtu, argv[0], 128, 4352); + + return area_set_lsp_mtu(vty, area, lsp_mtu); +} + +DEFUN(no_area_lsp_mtu, + no_area_lsp_mtu_cmd, + "no lsp-mtu", + NO_STR + "Configure the maximum size of generated LSPs\n") +{ + struct isis_area *area; + + area = vty->index; + if (!area) + { + vty_out (vty, "Can't find ISIS instance %s", VTY_NEWLINE); + return CMD_ERR_NO_MATCH; + } + + return area_set_lsp_mtu(vty, area, DEFAULT_LSP_MTU); +} + +ALIAS(no_area_lsp_mtu, + no_area_lsp_mtu_arg_cmd, + "no lsp-mtu <128-4352>", + NO_STR + "Configure the maximum size of generated LSPs\n" + "Maximum size of generated LSPs\n"); + DEFUN (area_passwd_md5, area_passwd_md5_cmd, "area-password md5 WORD", @@ -2991,6 +3059,12 @@ isis_config_write (struct vty *vty) write++; } } + if (area->lsp_mtu != DEFAULT_LSP_MTU) + { + vty_out(vty, " lsp-mtu %u%s", area->lsp_mtu, VTY_NEWLINE); + write++; + } + /* Minimum SPF interval. */ if (area->min_spf_interval[0] == area->min_spf_interval[1]) { @@ -3224,6 +3298,10 @@ isis_init () install_element (ISIS_NODE, &is_type_cmd); install_element (ISIS_NODE, &no_is_type_cmd); + install_element (ISIS_NODE, &area_lsp_mtu_cmd); + install_element (ISIS_NODE, &no_area_lsp_mtu_cmd); + install_element (ISIS_NODE, &no_area_lsp_mtu_arg_cmd); + install_element (ISIS_NODE, &area_passwd_md5_cmd); install_element (ISIS_NODE, &area_passwd_md5_snpauth_cmd); install_element (ISIS_NODE, &area_passwd_clear_cmd); diff --git a/isisd/isisd.h b/isisd/isisd.h index efebed9ce8..ea5f0a9ce5 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -93,7 +93,8 @@ struct isis_area struct isis_spftree *spftree6[ISIS_LEVELS]; /* The v6 SPTs */ struct route_table *route_table6[ISIS_LEVELS]; /* IPv6 routes */ #endif - unsigned int min_bcast_mtu; +#define DEFAULT_LSP_MTU 1497 + unsigned int lsp_mtu; /* Size of LSPs to generate */ struct list *circuit_list; /* IS-IS circuits */ struct flags flags; struct thread *t_tick; /* LSP walker */