isisd: allow to adjust lsp-mtu

Signed-off-by: Christian Franke <chris@opensourcerouting.org>
Acked-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Christian Franke 2015-11-10 18:43:31 +01:00 committed by Donald Sharp
parent 7ed55a412f
commit b20ccb3aa9
8 changed files with 172 additions and 63 deletions

View File

@ -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 int
isis_circuit_up (struct isis_circuit *circuit) isis_circuit_up (struct isis_circuit *circuit)
{ {
@ -588,6 +611,15 @@ isis_circuit_up (struct isis_circuit *circuit)
if (circuit->is_passive) if (circuit->is_passive)
return ISIS_OK; 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) 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[0] = list_new ();
circuit->u.bc.adjdb[1] = 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 * 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 */ /* initialize the circuit streams after opening connection */
if (circuit->rcv_stream == NULL) isis_circuit_stream(circuit, &circuit->rcv_stream);
circuit->rcv_stream = stream_new (ISO_MTU (circuit)); isis_circuit_stream(circuit, &circuit->snd_stream);
if (circuit->snd_stream == NULL)
circuit->snd_stream = stream_new (ISO_MTU (circuit));
#ifdef GNU_LINUX #ifdef GNU_LINUX
THREAD_READ_ON (master, circuit->t_read, isis_receive, circuit, THREAD_READ_ON (master, circuit->t_read, isis_receive, circuit,
@ -1192,6 +1218,7 @@ DEFUN (ip_router_isis,
struct isis_circuit *circuit; struct isis_circuit *circuit;
struct interface *ifp; struct interface *ifp;
struct isis_area *area; struct isis_area *area;
int rv;
ifp = (struct interface *) vty->index; ifp = (struct interface *) vty->index;
assert (ifp); assert (ifp);
@ -1220,16 +1247,25 @@ DEFUN (ip_router_isis,
area = vty->index; area = vty->index;
circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area); 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; circuit->ip_router = 1;
area->ip_circuits++; area->ip_circuits++;
circuit_update_nlpids (circuit); circuit_update_nlpids (circuit);
rv = CMD_SUCCESS;
}
vty->node = INTERFACE_NODE; vty->node = INTERFACE_NODE;
vty->index = ifp; vty->index = ifp;
return CMD_SUCCESS; return rv;
} }
DEFUN (no_ip_router_isis, DEFUN (no_ip_router_isis,
@ -1290,6 +1326,7 @@ DEFUN (ipv6_router_isis,
struct isis_circuit *circuit; struct isis_circuit *circuit;
struct interface *ifp; struct interface *ifp;
struct isis_area *area; struct isis_area *area;
int rv;
ifp = (struct interface *) vty->index; ifp = (struct interface *) vty->index;
assert (ifp); assert (ifp);
@ -1318,16 +1355,25 @@ DEFUN (ipv6_router_isis,
area = vty->index; area = vty->index;
circuit = isis_csm_state_change (ISIS_ENABLE, circuit, area); 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; circuit->ipv6_router = 1;
area->ipv6_circuits++; area->ipv6_circuits++;
circuit_update_nlpids (circuit); circuit_update_nlpids (circuit);
rv = CMD_SUCCESS;
}
vty->node = INTERFACE_NODE; vty->node = INTERFACE_NODE;
vty->index = ifp; vty->index = ifp;
return CMD_SUCCESS; return rv;
} }
DEFUN (no_ipv6_router_isis, DEFUN (no_ipv6_router_isis,

View File

@ -164,5 +164,7 @@ void isis_circuit_down (struct isis_circuit *);
void circuit_update_nlpids (struct isis_circuit *circuit); void circuit_update_nlpids (struct isis_circuit *circuit);
void isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty, void isis_circuit_print_vty (struct isis_circuit *circuit, struct vty *vty,
char detail); 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 */ #endif /* _ZEBRA_ISIS_CIRCUIT_H */

View File

@ -34,7 +34,6 @@
#define ISO_SAP 0xFE #define ISO_SAP 0xFE
#define INTRADOMAIN_ROUTEING_SELECTOR 0 #define INTRADOMAIN_ROUTEING_SELECTOR 0
#define SEQUENCE_MODULUS 4294967296 #define SEQUENCE_MODULUS 4294967296
#define RECEIVE_LSP_BUFFER_SIZE 1492
/* /*
* implementation specific jitter values * implementation specific jitter values

View File

@ -575,15 +575,16 @@ lsp_new_from_stream_ptr (struct stream *stream,
} }
struct isis_lsp * struct isis_lsp *
lsp_new (u_char * lsp_id, u_int16_t rem_lifetime, u_int32_t seq_num, lsp_new(struct isis_area *area, u_char * lsp_id,
u_int8_t lsp_bits, u_int16_t checksum, int level) 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; struct isis_lsp *lsp;
lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp)); lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp));
lsp->area = area;
/* FIXME: Should be minimal mtu? */ lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
lsp->pdu = stream_new (1500);
if (LSP_FRAGMENT (lsp_id) == 0) if (LSP_FRAGMENT (lsp_id) == 0)
lsp->lspu.frags = list_new (); lsp->lspu.frags = list_new ();
lsp->isis_header = (struct isis_fixed_hdr *) (STREAM_DATA (lsp->pdu)); 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); lsp_clear_data (lsp);
return 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, lsp_bits_generate (level, area->overload_bit,
area->attached_bit), 0, level); area->attached_bit), 0, level);
lsp->area = area; lsp->area = area;
@ -1593,7 +1594,7 @@ lsp_generate (struct isis_area *area, int level)
area->lspdb[level - 1]); area->lspdb[level - 1]);
} }
rem_lifetime = lsp_rem_lifetime (area, level); 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, area->is_type | area->overload_bit | area->attached_bit,
0, level); 0, level);
newlsp->area = area; newlsp->area = area;
@ -1966,7 +1967,7 @@ lsp_generate_pseudo (struct isis_circuit *circuit, int level)
rem_lifetime = lsp_rem_lifetime (circuit->area, level); rem_lifetime = lsp_rem_lifetime (circuit->area, level);
/* RFC3787 section 4 SHOULD not set overload bit in pseudo LSPs */ /* 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, circuit->area->is_type | circuit->area->attached_bit,
0, level); 0, level);
lsp->area = circuit->area; lsp->area = circuit->area;
@ -2356,8 +2357,7 @@ lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr,
lsp->area = area; lsp->area = area;
lsp->level = ((lsp_hdr->lsp_bits & LSPBIT_IST) == IS_LEVEL_1) ? lsp->level = ((lsp_hdr->lsp_bits & LSPBIT_IST) == IS_LEVEL_1) ?
IS_LEVEL_1 : IS_LEVEL_2; IS_LEVEL_1 : IS_LEVEL_2;
/* FIXME: Should be minimal mtu? */ lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
lsp->pdu = stream_new (1500);
lsp->isis_header = (struct isis_fixed_hdr *) STREAM_DATA (lsp->pdu); 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 fill_fixed_hdr (lsp->isis_header, (lsp->level == IS_LEVEL_1) ? L1_LINK_STATE
: L2_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); lspid[ISIS_SYS_ID_LEN - 2] = ((i >> 8) & 0xFF);
rem_lifetime = lsp_rem_lifetime (area, IS_LEVEL_1); rem_lifetime = lsp_rem_lifetime (area, IS_LEVEL_1);
lsp = lsp_new (lspid, rem_lifetime, 1, IS_LEVEL_1 | area->overload_bit lsp = lsp_new (area, lspid, rem_lifetime, 1,
| area->attached_bit, 0, 1); IS_LEVEL_1 | area->overload_bit | area->attached_bit,
0, 1);
if (!lsp) if (!lsp)
return; return;
lsp->area = area;
lsp->from_topology = 1; lsp->from_topology = 1;
/* Creating LSP data based on topology info. */ /* Creating LSP data based on topology info. */

View File

@ -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_generate_pseudo (struct isis_circuit *circuit, int level);
int lsp_regenerate_schedule_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_int32_t seq_num, u_int8_t lsp_bits,
u_int16_t checksum, int level); u_int16_t checksum, int level);
struct isis_lsp *lsp_new_from_stream_ptr (struct stream *stream, struct isis_lsp *lsp_new_from_stream_ptr (struct stream *stream,

View File

@ -1867,9 +1867,9 @@ process_snp (int snp_type, int level, struct isis_circuit *circuit,
if (entry->rem_lifetime && entry->checksum && entry->seq_num && if (entry->rem_lifetime && entry->checksum && entry->seq_num &&
memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN))
{ {
lsp = lsp_new (entry->lsp_id, ntohs (entry->rem_lifetime), lsp = lsp_new(circuit->area, entry->lsp_id,
0, 0, entry->checksum, level); ntohs(entry->rem_lifetime),
lsp->area = circuit->area; 0, 0, entry->checksum, level);
lsp_insert (lsp, circuit->area->lspdb[level - 1]); lsp_insert (lsp, circuit->area->lspdb[level - 1]);
ISIS_FLAGS_CLEAR_ALL (lsp->SRMflags); ISIS_FLAGS_CLEAR_ALL (lsp->SRMflags);
ISIS_SET_FLAG (lsp->SSNflags, circuit); ISIS_SET_FLAG (lsp->SSNflags, circuit);
@ -2093,10 +2093,7 @@ isis_receive (struct thread *thread)
circuit = THREAD_ARG (thread); circuit = THREAD_ARG (thread);
assert (circuit); assert (circuit);
if (circuit->rcv_stream == NULL) isis_circuit_stream(circuit, &circuit->rcv_stream);
circuit->rcv_stream = stream_new (ISO_MTU (circuit));
else
stream_reset (circuit->rcv_stream);
retval = circuit->rx (circuit, ssnpa); retval = circuit->rx (circuit, ssnpa);
circuit->t_read = NULL; circuit->t_read = NULL;
@ -2132,10 +2129,7 @@ isis_receive (struct thread *thread)
circuit->t_read = NULL; circuit->t_read = NULL;
if (circuit->rcv_stream == NULL) isis_circuit_stream(circuit, &circuit->rcv_stream);
circuit->rcv_stream = stream_new (ISO_MTU (circuit));
else
stream_reset (circuit->rcv_stream);
retval = circuit->rx (circuit, ssnpa); retval = circuit->rx (circuit, ssnpa);
@ -2240,10 +2234,7 @@ send_hello (struct isis_circuit *circuit, int level)
return ISIS_WARNING; return ISIS_WARNING;
} }
if (!circuit->snd_stream) isis_circuit_stream(circuit, &circuit->snd_stream);
circuit->snd_stream = stream_new (ISO_MTU (circuit));
else
stream_reset (circuit->snd_stream);
if (circuit->circ_type == CIRCUIT_T_BROADCAST) if (circuit->circ_type == CIRCUIT_T_BROADCAST)
if (level == IS_LEVEL_1) 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; unsigned long auth_tlv_offset = 0;
int retval = ISIS_OK; int retval = ISIS_OK;
if (circuit->snd_stream == NULL) isis_circuit_stream(circuit, &circuit->snd_stream);
circuit->snd_stream = stream_new (ISO_MTU (circuit));
else
stream_reset (circuit->snd_stream);
if (level == IS_LEVEL_1) if (level == IS_LEVEL_1)
fill_fixed_hdr_andstream (&fixed_hdr, L1_COMPLETE_SEQ_NUM, 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; unsigned long auth_tlv_offset = 0;
int retval = ISIS_OK; int retval = ISIS_OK;
if (circuit->snd_stream == NULL) isis_circuit_stream(circuit, &circuit->snd_stream);
circuit->snd_stream = stream_new (ISO_MTU (circuit));
else
stream_reset (circuit->snd_stream);
if (level == IS_LEVEL_1) if (level == IS_LEVEL_1)
fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM, 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; u_int16_t length;
struct isis_fixed_hdr fixed_hdr; struct isis_fixed_hdr fixed_hdr;
if (!circuit->snd_stream) isis_circuit_stream(circuit, &circuit->snd_stream);
circuit->snd_stream = stream_new (ISO_MTU (circuit));
else
stream_reset (circuit->snd_stream);
// fill_llc_hdr (stream); // fill_llc_hdr (stream);
if (level == IS_LEVEL_1) if (level == IS_LEVEL_1)

View File

@ -158,13 +158,11 @@ isis_area_create (const char *area_tag)
area->oldmetric = 0; area->oldmetric = 0;
area->newmetric = 1; area->newmetric = 1;
area->lsp_frag_threshold = 90; area->lsp_frag_threshold = 90;
area->lsp_mtu = DEFAULT_LSP_MTU;
#ifdef TOPOLOGY_GENERATE #ifdef TOPOLOGY_GENERATE
memcpy (area->topology_baseis, DEFAULT_TOPOLOGY_BASEIS, ISIS_SYS_ID_LEN); memcpy (area->topology_baseis, DEFAULT_TOPOLOGY_BASEIS, ISIS_SYS_ID_LEN);
#endif /* TOPOLOGY_GENERATE */ #endif /* TOPOLOGY_GENERATE */
/* FIXME: Think of a better way... */
area->min_bcast_mtu = 1497;
area->area_tag = strdup (area_tag); area->area_tag = strdup (area_tag);
listnode_add (isis->area_list, area); listnode_add (isis->area_list, area);
area->isis = isis; area->isis = isis;
@ -1546,6 +1544,76 @@ DEFUN (no_net,
return area_clear_net_title (vty, argv[0]); 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, DEFUN (area_passwd_md5,
area_passwd_md5_cmd, area_passwd_md5_cmd,
"area-password md5 WORD", "area-password md5 WORD",
@ -2991,6 +3059,12 @@ isis_config_write (struct vty *vty)
write++; write++;
} }
} }
if (area->lsp_mtu != DEFAULT_LSP_MTU)
{
vty_out(vty, " lsp-mtu %u%s", area->lsp_mtu, VTY_NEWLINE);
write++;
}
/* Minimum SPF interval. */ /* Minimum SPF interval. */
if (area->min_spf_interval[0] == area->min_spf_interval[1]) 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, &is_type_cmd);
install_element (ISIS_NODE, &no_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_cmd);
install_element (ISIS_NODE, &area_passwd_md5_snpauth_cmd); install_element (ISIS_NODE, &area_passwd_md5_snpauth_cmd);
install_element (ISIS_NODE, &area_passwd_clear_cmd); install_element (ISIS_NODE, &area_passwd_clear_cmd);

View File

@ -93,7 +93,8 @@ struct isis_area
struct isis_spftree *spftree6[ISIS_LEVELS]; /* The v6 SPTs */ struct isis_spftree *spftree6[ISIS_LEVELS]; /* The v6 SPTs */
struct route_table *route_table6[ISIS_LEVELS]; /* IPv6 routes */ struct route_table *route_table6[ISIS_LEVELS]; /* IPv6 routes */
#endif #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 list *circuit_list; /* IS-IS circuits */
struct flags flags; struct flags flags;
struct thread *t_tick; /* LSP walker */ struct thread *t_tick; /* LSP walker */