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
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,

View File

@ -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 */

View File

@ -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

View File

@ -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. */

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_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,

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 &&
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)

View File

@ -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);

View File

@ -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 */