version 1.1.1.2, 2012/10/09 09:22:28
|
version 1.1.1.4, 2016/11/02 10:09:10
|
Line 5
|
Line 5
|
* Copyright (C) 2001,2002 Sampo Saaristo |
* Copyright (C) 2001,2002 Sampo Saaristo |
* Tampere University of Technology |
* Tampere University of Technology |
* Institute of Communications Engineering |
* Institute of Communications Engineering |
|
* Copyright (C) 2013-2015 Christian Franke <chris@opensourcerouting.org> |
* |
* |
* This program is free software; you can redistribute it and/or modify it |
* This program is free software; you can redistribute it and/or modify it |
* under the terms of the GNU General Public Licenseas published by the Free | * under the terms of the GNU General Public License as published by the Free |
* Software Foundation; either version 2 of the License, or (at your option) |
* Software Foundation; either version 2 of the License, or (at your option) |
* any later version. |
* any later version. |
* |
* |
Line 35
|
Line 36
|
#include "if.h" |
#include "if.h" |
#include "checksum.h" |
#include "checksum.h" |
#include "md5.h" |
#include "md5.h" |
|
#include "table.h" |
|
|
#include "isisd/dict.h" |
#include "isisd/dict.h" |
#include "isisd/isis_constants.h" |
#include "isisd/isis_constants.h" |
Line 271 lsp_compare (char *areatag, struct isis_lsp *lsp, u_in
|
Line 273 lsp_compare (char *areatag, struct isis_lsp *lsp, u_in
|
return LSP_EQUAL; |
return LSP_EQUAL; |
} |
} |
|
|
if (ntohl (seq_num) >= ntohl (lsp->lsp_header->seq_num)) | /* |
| * LSPs with identical checksums should only be treated as newer if: |
| * a) The current LSP has a remaining lifetime != 0 and the other LSP has a |
| * remaining lifetime == 0. In this case, we should participate in the purge |
| * and should not treat the current LSP with remaining lifetime == 0 as older. |
| * b) The LSP has an incorrect checksum. In this case, we need to react as given |
| * in 7.3.16.2. |
| */ |
| if (ntohl (seq_num) > ntohl (lsp->lsp_header->seq_num) |
| || (ntohl(seq_num) == ntohl(lsp->lsp_header->seq_num) |
| && ( (lsp->lsp_header->rem_lifetime != 0 |
| && rem_lifetime == 0) |
| || lsp->lsp_header->checksum != checksum))) |
{ |
{ |
if (isis->debugs & DEBUG_SNP_PACKETS) |
if (isis->debugs & DEBUG_SNP_PACKETS) |
{ |
{ |
Line 379 lsp_auth_update (struct isis_lsp *lsp)
|
Line 393 lsp_auth_update (struct isis_lsp *lsp)
|
/* Compute autentication value */ |
/* Compute autentication value */ |
hmac_md5 (STREAM_DATA (lsp->pdu), stream_get_endp(lsp->pdu), |
hmac_md5 (STREAM_DATA (lsp->pdu), stream_get_endp(lsp->pdu), |
(unsigned char *) &passwd->passwd, passwd->len, |
(unsigned char *) &passwd->passwd, passwd->len, |
(caddr_t) &hmac_md5_hash); | (unsigned char *) &hmac_md5_hash); |
/* Copy the hash into the stream */ |
/* Copy the hash into the stream */ |
memcpy (STREAM_DATA (lsp->pdu) + lsp->auth_tlv_offset + 3, |
memcpy (STREAM_DATA (lsp->pdu) + lsp->auth_tlv_offset + 3, |
hmac_md5_hash, ISIS_AUTH_MD5_SIZE); |
hmac_md5_hash, ISIS_AUTH_MD5_SIZE); |
Line 442 lsp_seqnum_update (struct isis_lsp *lsp0)
|
Line 456 lsp_seqnum_update (struct isis_lsp *lsp0)
|
} |
} |
|
|
static u_int8_t |
static u_int8_t |
lsp_bits_generate (int level, int overload_bit) | lsp_bits_generate (int level, int overload_bit, int attached_bit) |
{ |
{ |
u_int8_t lsp_bits = 0; |
u_int8_t lsp_bits = 0; |
if (level == IS_LEVEL_1) |
if (level == IS_LEVEL_1) |
Line 451 lsp_bits_generate (int level, int overload_bit)
|
Line 465 lsp_bits_generate (int level, int overload_bit)
|
lsp_bits = IS_LEVEL_1_AND_2; |
lsp_bits = IS_LEVEL_1_AND_2; |
if (overload_bit) |
if (overload_bit) |
lsp_bits |= overload_bit; |
lsp_bits |= overload_bit; |
|
if (attached_bit) |
|
lsp_bits |= attached_bit; |
return lsp_bits; |
return lsp_bits; |
} |
} |
|
|
Line 573 lsp_new_from_stream_ptr (struct stream *stream,
|
Line 589 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)); |
if (!lsp) | lsp->area = area; |
{ | |
/* FIXME: set lspdbol bit */ | lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu); |
zlog_warn ("lsp_new(): out of memory"); | |
return NULL; | |
} | |
/* FIXME: Should be minimal 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)); |
Line 950 lsp_print_detail (struct isis_lsp *lsp, struct vty *vt
|
Line 962 lsp_print_detail (struct isis_lsp *lsp, struct vty *vt
|
memcpy (in6.s6_addr, ipv6_reach->prefix, |
memcpy (in6.s6_addr, ipv6_reach->prefix, |
PSIZE (ipv6_reach->prefix_len)); |
PSIZE (ipv6_reach->prefix_len)); |
inet_ntop (AF_INET6, &in6, (char *)buff, BUFSIZ); |
inet_ntop (AF_INET6, &in6, (char *)buff, BUFSIZ); |
if ((ipv6_reach->control_info && | if ((ipv6_reach->control_info & |
CTRL_INFO_DISTRIBUTION) == DISTRIBUTION_INTERNAL) |
CTRL_INFO_DISTRIBUTION) == DISTRIBUTION_INTERNAL) |
vty_out (vty, " Metric : %-8d IPv6-Internal : %s/%d%s", |
vty_out (vty, " Metric : %-8d IPv6-Internal : %s/%d%s", |
ntohl (ipv6_reach->metric), |
ntohl (ipv6_reach->metric), |
Line 1089 lsp_rem_lifetime (struct isis_area *area, int level)
|
Line 1101 lsp_rem_lifetime (struct isis_area *area, int level)
|
MAX_AGE_JITTER); |
MAX_AGE_JITTER); |
|
|
/* No jitter if the max refresh will be less than configure gen interval */ |
/* No jitter if the max refresh will be less than configure gen interval */ |
|
/* N.B. this calucation is acceptable since rem_lifetime is in [332,65535] at |
|
* this point */ |
if (area->lsp_gen_interval[level - 1] > (rem_lifetime - 300)) |
if (area->lsp_gen_interval[level - 1] > (rem_lifetime - 300)) |
rem_lifetime = area->max_lsp_lifetime[level - 1]; |
rem_lifetime = area->max_lsp_lifetime[level - 1]; |
|
|
Line 1112 lsp_refresh_time (struct isis_lsp *lsp, u_int16_t rem_
|
Line 1126 lsp_refresh_time (struct isis_lsp *lsp, u_int16_t rem_
|
refresh_time > (rem_lifetime - 300)) |
refresh_time > (rem_lifetime - 300)) |
refresh_time = rem_lifetime - 300; |
refresh_time = rem_lifetime - 300; |
|
|
assert (area->lsp_gen_interval[level - 1] < refresh_time); | /* In cornercases, refresh_time might be <= lsp_gen_interval, however |
| * we accept this violation to satisfy refresh_time <= rem_lifetime - 300 */ |
|
|
return refresh_time; |
return refresh_time; |
} |
} |
Line 1134 lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0,
|
Line 1149 lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0,
|
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), 0, level); | lsp_bits_generate (level, area->overload_bit, |
| area->attached_bit), 0, level); |
lsp->area = area; |
lsp->area = area; |
lsp->own_lsp = 1; |
lsp->own_lsp = 1; |
lsp_insert (lsp, area->lspdb[level - 1]); |
lsp_insert (lsp, area->lspdb[level - 1]); |
Line 1144 lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0,
|
Line 1160 lsp_next_frag (u_char frag_num, struct isis_lsp *lsp0,
|
return lsp; |
return lsp; |
} |
} |
|
|
|
static void |
|
lsp_build_ext_reach_ipv4(struct isis_lsp *lsp, struct isis_area *area, |
|
struct tlvs *tlv_data) |
|
{ |
|
struct route_table *er_table; |
|
struct route_node *rn; |
|
struct prefix_ipv4 *ipv4; |
|
struct isis_ext_info *info; |
|
struct ipv4_reachability *ipreach; |
|
struct te_ipv4_reachability *te_ipreach; |
|
|
|
er_table = get_ext_reach(area, AF_INET, lsp->level); |
|
if (!er_table) |
|
return; |
|
|
|
for (rn = route_top(er_table); rn; rn = route_next(rn)) |
|
{ |
|
if (!rn->info) |
|
continue; |
|
|
|
ipv4 = (struct prefix_ipv4*)&rn->p; |
|
info = rn->info; |
|
if (area->oldmetric) |
|
{ |
|
if (tlv_data->ipv4_ext_reachs == NULL) |
|
{ |
|
tlv_data->ipv4_ext_reachs = list_new(); |
|
tlv_data->ipv4_ext_reachs->del = free_tlv; |
|
} |
|
ipreach = XMALLOC(MTYPE_ISIS_TLV, sizeof(*ipreach)); |
|
|
|
ipreach->prefix.s_addr = ipv4->prefix.s_addr; |
|
masklen2ip(ipv4->prefixlen, &ipreach->mask); |
|
ipreach->prefix.s_addr &= ipreach->mask.s_addr; |
|
|
|
if ((info->metric & 0x3f) != info->metric) |
|
ipreach->metrics.metric_default = 0x3f; |
|
else |
|
ipreach->metrics.metric_default = info->metric; |
|
ipreach->metrics.metric_expense = METRICS_UNSUPPORTED; |
|
ipreach->metrics.metric_error = METRICS_UNSUPPORTED; |
|
ipreach->metrics.metric_delay = METRICS_UNSUPPORTED; |
|
listnode_add(tlv_data->ipv4_ext_reachs, ipreach); |
|
} |
|
if (area->newmetric) |
|
{ |
|
if (tlv_data->te_ipv4_reachs == NULL) |
|
{ |
|
tlv_data->te_ipv4_reachs = list_new(); |
|
tlv_data->te_ipv4_reachs->del = free_tlv; |
|
} |
|
te_ipreach = |
|
XCALLOC(MTYPE_ISIS_TLV, |
|
sizeof(*te_ipreach) - 1 + PSIZE(ipv4->prefixlen)); |
|
if (info->metric > MAX_WIDE_PATH_METRIC) |
|
te_ipreach->te_metric = htonl(MAX_WIDE_PATH_METRIC); |
|
else |
|
te_ipreach->te_metric = htonl(info->metric); |
|
te_ipreach->control = ipv4->prefixlen & 0x3f; |
|
memcpy(&te_ipreach->prefix_start, &ipv4->prefix.s_addr, |
|
PSIZE(ipv4->prefixlen)); |
|
listnode_add(tlv_data->te_ipv4_reachs, te_ipreach); |
|
} |
|
} |
|
} |
|
|
|
static void |
|
lsp_build_ext_reach_ipv6(struct isis_lsp *lsp, struct isis_area *area, |
|
struct tlvs *tlv_data) |
|
{ |
|
struct route_table *er_table; |
|
struct route_node *rn; |
|
struct prefix_ipv6 *ipv6; |
|
struct isis_ext_info *info; |
|
struct ipv6_reachability *ip6reach; |
|
|
|
er_table = get_ext_reach(area, AF_INET6, lsp->level); |
|
if (!er_table) |
|
return; |
|
|
|
for (rn = route_top(er_table); rn; rn = route_next(rn)) |
|
{ |
|
if (!rn->info) |
|
continue; |
|
|
|
ipv6 = (struct prefix_ipv6*)&rn->p; |
|
info = rn->info; |
|
|
|
if (tlv_data->ipv6_reachs == NULL) |
|
{ |
|
tlv_data->ipv6_reachs = list_new(); |
|
tlv_data->ipv6_reachs->del = free_tlv; |
|
} |
|
ip6reach = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ip6reach)); |
|
if (info->metric > MAX_WIDE_PATH_METRIC) |
|
ip6reach->metric = htonl(MAX_WIDE_PATH_METRIC); |
|
else |
|
ip6reach->metric = htonl(info->metric); |
|
ip6reach->control_info = DISTRIBUTION_EXTERNAL; |
|
ip6reach->prefix_len = ipv6->prefixlen; |
|
memcpy(ip6reach->prefix, ipv6->prefix.s6_addr, sizeof(ip6reach->prefix)); |
|
listnode_add(tlv_data->ipv6_reachs, ip6reach); |
|
} |
|
} |
|
|
|
static void |
|
lsp_build_ext_reach (struct isis_lsp *lsp, struct isis_area *area, |
|
struct tlvs *tlv_data) |
|
{ |
|
lsp_build_ext_reach_ipv4(lsp, area, tlv_data); |
|
lsp_build_ext_reach_ipv6(lsp, area, tlv_data); |
|
} |
|
|
/* |
/* |
* Builds the LSP data part. This func creates a new frag whenever |
* Builds the LSP data part. This func creates a new frag whenever |
* area->lsp_frag_threshold is exceeded. |
* area->lsp_frag_threshold is exceeded. |
Line 1161 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1290 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
struct te_ipv4_reachability *te_ipreach; |
struct te_ipv4_reachability *te_ipreach; |
struct isis_adjacency *nei; |
struct isis_adjacency *nei; |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
struct prefix_ipv6 *ipv6, *ip6prefix; | struct prefix_ipv6 *ipv6, ip6prefix; |
struct ipv6_reachability *ip6reach; |
struct ipv6_reachability *ip6reach; |
#endif /* HAVE_IPV6 */ |
#endif /* HAVE_IPV6 */ |
struct tlvs tlv_data; |
struct tlvs tlv_data; |
Line 1171 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1300 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
uint32_t metric; |
uint32_t metric; |
u_char zero_id[ISIS_SYS_ID_LEN + 1]; |
u_char zero_id[ISIS_SYS_ID_LEN + 1]; |
int retval = ISIS_OK; |
int retval = ISIS_OK; |
|
char buf[BUFSIZ]; |
|
|
|
lsp_debug("ISIS (%s): Constructing local system LSP for level %d", area->area_tag, level); |
|
|
/* |
/* |
* Building the zero lsp |
* Building the zero lsp |
*/ |
*/ |
Line 1210 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1342 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
lsp->tlv_data.nlpids->count = 0; |
lsp->tlv_data.nlpids->count = 0; |
if (area->ip_circuits > 0) |
if (area->ip_circuits > 0) |
{ |
{ |
|
lsp_debug("ISIS (%s): Found IPv4 circuit, adding IPv4 to NLPIDs", area->area_tag); |
lsp->tlv_data.nlpids->count++; |
lsp->tlv_data.nlpids->count++; |
lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP; |
lsp->tlv_data.nlpids->nlpids[0] = NLPID_IP; |
} |
} |
#ifdef HAVE_IPV6 |
#ifdef HAVE_IPV6 |
if (area->ipv6_circuits > 0) |
if (area->ipv6_circuits > 0) |
{ |
{ |
|
lsp_debug("ISIS (%s): Found IPv6 circuit, adding IPv6 to NLPIDs", area->area_tag); |
lsp->tlv_data.nlpids->count++; |
lsp->tlv_data.nlpids->count++; |
lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] = |
lsp->tlv_data.nlpids->nlpids[lsp->tlv_data.nlpids->count - 1] = |
NLPID_IPV6; |
NLPID_IPV6; |
Line 1227 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1361 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
/* Dynamic Hostname */ |
/* Dynamic Hostname */ |
if (area->dynhostname) |
if (area->dynhostname) |
{ |
{ |
|
const char *hostname = unix_hostname(); |
|
size_t hostname_len = strlen(hostname); |
|
|
lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV, |
lsp->tlv_data.hostname = XMALLOC (MTYPE_ISIS_TLV, |
sizeof (struct hostname)); |
sizeof (struct hostname)); |
|
|
memcpy (lsp->tlv_data.hostname->name, unix_hostname (), | strncpy((char *)lsp->tlv_data.hostname->name, hostname, |
strlen (unix_hostname ())); | sizeof(lsp->tlv_data.hostname->name)); |
lsp->tlv_data.hostname->namelen = strlen (unix_hostname ()); | if (hostname_len <= MAX_TLV_LEN) |
| lsp->tlv_data.hostname->namelen = hostname_len; |
| else |
| lsp->tlv_data.hostname->namelen = MAX_TLV_LEN; |
| |
| lsp_debug("ISIS (%s): Adding dynamic hostname '%.*s'", area->area_tag, |
| lsp->tlv_data.hostname->namelen, lsp->tlv_data.hostname->name); |
tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu); |
tlv_add_dynamic_hostname (lsp->tlv_data.hostname, lsp->pdu); |
} |
} |
|
else |
|
{ |
|
lsp_debug("ISIS (%s): Not adding dynamic hostname (disabled)", area->area_tag); |
|
} |
|
|
/* IPv4 address and TE router ID TLVs. In case of the first one we don't |
/* IPv4 address and TE router ID TLVs. In case of the first one we don't |
* follow "C" vendor, but "J" vendor behavior - one IPv4 address is put into |
* follow "C" vendor, but "J" vendor behavior - one IPv4 address is put into |
* LSP and this address is same as router id. */ |
* LSP and this address is same as router id. */ |
if (isis->router_id != 0) |
if (isis->router_id != 0) |
{ |
{ |
|
inet_ntop(AF_INET, &isis->router_id, buf, sizeof(buf)); |
|
lsp_debug("ISIS (%s): Adding router ID %s as IPv4 tlv.", area->area_tag, buf); |
if (lsp->tlv_data.ipv4_addrs == NULL) |
if (lsp->tlv_data.ipv4_addrs == NULL) |
{ |
{ |
lsp->tlv_data.ipv4_addrs = list_new (); |
lsp->tlv_data.ipv4_addrs = list_new (); |
Line 1256 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1405 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
* TLV's are in use. */ |
* TLV's are in use. */ |
if (area->newmetric) |
if (area->newmetric) |
{ |
{ |
|
lsp_debug("ISIS (%s): Adding router ID also as TE router ID tlv.", area->area_tag); |
lsp->tlv_data.router_id = XMALLOC (MTYPE_ISIS_TLV, |
lsp->tlv_data.router_id = XMALLOC (MTYPE_ISIS_TLV, |
sizeof (struct in_addr)); |
sizeof (struct in_addr)); |
lsp->tlv_data.router_id->id.s_addr = isis->router_id; |
lsp->tlv_data.router_id->id.s_addr = isis->router_id; |
Line 1263 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1413 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
TE_ROUTER_ID); |
TE_ROUTER_ID); |
} |
} |
} |
} |
|
else |
|
{ |
|
lsp_debug("ISIS (%s): Router ID is unset. Not adding tlv.", area->area_tag); |
|
} |
|
|
memset (&tlv_data, 0, sizeof (struct tlvs)); |
memset (&tlv_data, 0, sizeof (struct tlvs)); |
|
|
Line 1289 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1443 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
} |
} |
#endif /* TOPOLOGY_GENERATE */ |
#endif /* TOPOLOGY_GENERATE */ |
|
|
|
lsp_debug("ISIS (%s): Adding circuit specific information.", area->area_tag); |
|
|
/* |
/* |
* Then build lists of tlvs related to circuits |
* Then build lists of tlvs related to circuits |
*/ |
*/ |
for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) |
for (ALL_LIST_ELEMENTS_RO (area->circuit_list, node, circuit)) |
{ |
{ |
|
if (!circuit->interface) |
|
lsp_debug("ISIS (%s): Processing %s circuit %p with unknown interface", |
|
area->area_tag, circuit_type2string(circuit->circ_type), circuit); |
|
else |
|
lsp_debug("ISIS (%s): Processing %s circuit %s", |
|
area->area_tag, circuit_type2string(circuit->circ_type), circuit->interface->name); |
|
|
if (circuit->state != C_STATE_UP) |
if (circuit->state != C_STATE_UP) |
continue; | { |
| lsp_debug("ISIS (%s): Circuit is not up, ignoring.", area->area_tag); |
| continue; |
| } |
|
|
/* |
/* |
* Add IPv4 internal reachability of this circuit |
* Add IPv4 internal reachability of this circuit |
Line 1303 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1469 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
if (circuit->ip_router && circuit->ip_addrs && |
if (circuit->ip_router && circuit->ip_addrs && |
circuit->ip_addrs->count > 0) |
circuit->ip_addrs->count > 0) |
{ |
{ |
|
lsp_debug("ISIS (%s): Circuit has IPv4 active, adding respective TLVs.", area->area_tag); |
if (area->oldmetric) |
if (area->oldmetric) |
{ |
{ |
if (tlv_data.ipv4_int_reachs == NULL) |
if (tlv_data.ipv4_int_reachs == NULL) |
Line 1318 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1485 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
masklen2ip (ipv4->prefixlen, &ipreach->mask); |
masklen2ip (ipv4->prefixlen, &ipreach->mask); |
ipreach->prefix.s_addr = ((ipreach->mask.s_addr) & |
ipreach->prefix.s_addr = ((ipreach->mask.s_addr) & |
(ipv4->prefix.s_addr)); |
(ipv4->prefix.s_addr)); |
|
inet_ntop(AF_INET, &ipreach->prefix.s_addr, buf, sizeof(buf)); |
|
lsp_debug("ISIS (%s): Adding old-style IP reachability for %s/%d", |
|
area->area_tag, buf, ipv4->prefixlen); |
listnode_add (tlv_data.ipv4_int_reachs, ipreach); |
listnode_add (tlv_data.ipv4_int_reachs, ipreach); |
} |
} |
} |
} |
Line 1343 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1513 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
te_ipreach->control = (ipv4->prefixlen & 0x3F); |
te_ipreach->control = (ipv4->prefixlen & 0x3F); |
memcpy (&te_ipreach->prefix_start, &ipv4->prefix.s_addr, |
memcpy (&te_ipreach->prefix_start, &ipv4->prefix.s_addr, |
(ipv4->prefixlen + 7)/8); |
(ipv4->prefixlen + 7)/8); |
|
inet_ntop(AF_INET, &ipv4->prefix.s_addr, buf, sizeof(buf)); |
|
lsp_debug("ISIS (%s): Adding te-style IP reachability for %s/%d", |
|
area->area_tag, buf, ipv4->prefixlen); |
listnode_add (tlv_data.te_ipv4_reachs, te_ipreach); |
listnode_add (tlv_data.te_ipv4_reachs, te_ipreach); |
} |
} |
} |
} |
Line 1374 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1547 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
|
|
ip6reach->control_info = 0; |
ip6reach->control_info = 0; |
ip6reach->prefix_len = ipv6->prefixlen; |
ip6reach->prefix_len = ipv6->prefixlen; |
memcpy (&ip6prefix, &ipv6, sizeof(ip6prefix)); | memcpy(&ip6prefix, ipv6, sizeof(ip6prefix)); |
apply_mask_ipv6 (ip6prefix); | apply_mask_ipv6(&ip6prefix); |
memcpy (ip6reach->prefix, ip6prefix->prefix.s6_addr, | |
| inet_ntop(AF_INET6, &ip6prefix.prefix.s6_addr, buf, sizeof(buf)); |
| lsp_debug("ISIS (%s): Adding IPv6 reachability for %s/%d", |
| area->area_tag, buf, ipv6->prefixlen); |
| |
| memcpy (ip6reach->prefix, ip6prefix.prefix.s6_addr, |
sizeof (ip6reach->prefix)); |
sizeof (ip6reach->prefix)); |
listnode_add (tlv_data.ipv6_reachs, ip6reach); |
listnode_add (tlv_data.ipv6_reachs, ip6reach); |
} |
} |
Line 1405 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1583 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
is_neigh->metrics = circuit->metrics[level - 1]; |
is_neigh->metrics = circuit->metrics[level - 1]; |
if (!memcmp (is_neigh->neigh_id, zero_id, |
if (!memcmp (is_neigh->neigh_id, zero_id, |
ISIS_SYS_ID_LEN + 1)) |
ISIS_SYS_ID_LEN + 1)) |
XFREE (MTYPE_ISIS_TLV, is_neigh); | { |
| XFREE (MTYPE_ISIS_TLV, is_neigh); |
| lsp_debug("ISIS (%s): No DIS for circuit, not adding old-style IS neighbor.", |
| area->area_tag); |
| } |
else |
else |
listnode_add (tlv_data.is_neighs, is_neigh); | { |
| listnode_add (tlv_data.is_neighs, is_neigh); |
| lsp_debug("ISIS (%s): Adding DIS %s.%02x as old-style neighbor", |
| area->area_tag, sysid_print(is_neigh->neigh_id), |
| LSP_PSEUDO_ID(is_neigh->neigh_id)); |
| } |
} |
} |
if (area->newmetric) |
if (area->newmetric) |
{ |
{ |
Line 1431 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1618 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
SET_TE_METRIC(te_is_neigh, metric); |
SET_TE_METRIC(te_is_neigh, metric); |
if (!memcmp (te_is_neigh->neigh_id, zero_id, |
if (!memcmp (te_is_neigh->neigh_id, zero_id, |
ISIS_SYS_ID_LEN + 1)) |
ISIS_SYS_ID_LEN + 1)) |
XFREE (MTYPE_ISIS_TLV, te_is_neigh); | { |
| XFREE (MTYPE_ISIS_TLV, te_is_neigh); |
| lsp_debug("ISIS (%s): No DIS for circuit, not adding te-style IS neighbor.", |
| area->area_tag); |
| } |
else |
else |
listnode_add (tlv_data.te_is_neighs, te_is_neigh); | { |
| listnode_add (tlv_data.te_is_neighs, te_is_neigh); |
| lsp_debug("ISIS (%s): Adding DIS %s.%02x as te-style neighbor", |
| area->area_tag, sysid_print(te_is_neigh->neigh_id), |
| LSP_PSEUDO_ID(te_is_neigh->neigh_id)); |
| } |
} |
} |
} |
} |
|
else |
|
{ |
|
lsp_debug("ISIS (%s): Circuit is not active for current level. Not adding IS neighbors", |
|
area->area_tag); |
|
} |
break; |
break; |
case CIRCUIT_T_P2P: |
case CIRCUIT_T_P2P: |
nei = circuit->u.p2p.neighbor; |
nei = circuit->u.p2p.neighbor; |
Line 1452 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1653 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
memcpy (is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN); |
memcpy (is_neigh->neigh_id, nei->sysid, ISIS_SYS_ID_LEN); |
is_neigh->metrics = circuit->metrics[level - 1]; |
is_neigh->metrics = circuit->metrics[level - 1]; |
listnode_add (tlv_data.is_neighs, is_neigh); |
listnode_add (tlv_data.is_neighs, is_neigh); |
|
lsp_debug("ISIS (%s): Adding old-style is reach for %s", area->area_tag, |
|
sysid_print(is_neigh->neigh_id)); |
} |
} |
if (area->newmetric) |
if (area->newmetric) |
{ |
{ |
Line 1468 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1671 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
metric = circuit->te_metric[level - 1]; |
metric = circuit->te_metric[level - 1]; |
SET_TE_METRIC(te_is_neigh, metric); |
SET_TE_METRIC(te_is_neigh, metric); |
listnode_add (tlv_data.te_is_neighs, te_is_neigh); |
listnode_add (tlv_data.te_is_neighs, te_is_neigh); |
|
lsp_debug("ISIS (%s): Adding te-style is reach for %s", area->area_tag, |
|
sysid_print(te_is_neigh->neigh_id)); |
} |
} |
} |
} |
|
else |
|
{ |
|
lsp_debug("ISIS (%s): No adjacency for given level on this circuit. Not adding IS neighbors", |
|
area->area_tag); |
|
} |
break; |
break; |
case CIRCUIT_T_LOOPBACK: |
case CIRCUIT_T_LOOPBACK: |
break; |
break; |
Line 1478 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1688 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
} |
} |
} |
} |
|
|
|
lsp_build_ext_reach(lsp, area, &tlv_data); |
|
|
|
lsp_debug("ISIS (%s): LSP construction is complete. Serializing...", area->area_tag); |
|
|
while (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs)) |
while (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs)) |
{ |
{ |
if (lsp->tlv_data.ipv4_int_reachs == NULL) |
if (lsp->tlv_data.ipv4_int_reachs == NULL) |
Line 1485 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
Line 1699 lsp_build (struct isis_lsp *lsp, struct isis_area *are
|
lsp_tlv_fit (lsp, &tlv_data.ipv4_int_reachs, |
lsp_tlv_fit (lsp, &tlv_data.ipv4_int_reachs, |
&lsp->tlv_data.ipv4_int_reachs, |
&lsp->tlv_data.ipv4_int_reachs, |
IPV4_REACH_LEN, area->lsp_frag_threshold, |
IPV4_REACH_LEN, area->lsp_frag_threshold, |
tlv_add_ipv4_reachs); | tlv_add_ipv4_int_reachs); |
if (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs)) |
if (tlv_data.ipv4_int_reachs && listcount (tlv_data.ipv4_int_reachs)) |
lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, |
lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, |
lsp0, area, level); |
lsp0, area, level); |
} |
} |
|
|
|
while (tlv_data.ipv4_ext_reachs && listcount (tlv_data.ipv4_ext_reachs)) |
|
{ |
|
if (lsp->tlv_data.ipv4_ext_reachs == NULL) |
|
lsp->tlv_data.ipv4_ext_reachs = list_new (); |
|
lsp_tlv_fit (lsp, &tlv_data.ipv4_ext_reachs, |
|
&lsp->tlv_data.ipv4_ext_reachs, |
|
IPV4_REACH_LEN, area->lsp_frag_threshold, |
|
tlv_add_ipv4_ext_reachs); |
|
if (tlv_data.ipv4_ext_reachs && listcount (tlv_data.ipv4_ext_reachs)) |
|
lsp = lsp_next_frag (LSP_FRAGMENT (lsp->lsp_header->lsp_id) + 1, |
|
lsp0, area, level); |
|
} |
|
|
/* FIXME: We pass maximum te_ipv4_reachability length to the lsp_tlv_fit() |
/* FIXME: We pass maximum te_ipv4_reachability length to the lsp_tlv_fit() |
* for now. lsp_tlv_fit() needs to be fixed to deal with variable length |
* for now. lsp_tlv_fit() needs to be fixed to deal with variable length |
* TLVs (sub TLVs!). */ |
* TLVs (sub TLVs!). */ |
Line 1588 lsp_generate (struct isis_area *area, int level)
|
Line 1815 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, 0, level); | area->is_type | area->overload_bit | area->attached_bit, |
| 0, level); |
newlsp->area = area; |
newlsp->area = area; |
newlsp->own_lsp = 1; |
newlsp->own_lsp = 1; |
|
|
Line 1598 lsp_generate (struct isis_area *area, int level)
|
Line 1826 lsp_generate (struct isis_area *area, int level)
|
lsp_build (newlsp, area); |
lsp_build (newlsp, area); |
/* time to calculate our checksum */ |
/* time to calculate our checksum */ |
lsp_seqnum_update (newlsp); |
lsp_seqnum_update (newlsp); |
|
newlsp->last_generated = time(NULL); |
lsp_set_all_srmflags (newlsp); |
lsp_set_all_srmflags (newlsp); |
|
|
refresh_time = lsp_refresh_time (newlsp, rem_lifetime); |
refresh_time = lsp_refresh_time (newlsp, rem_lifetime); |
|
|
THREAD_TIMER_OFF (area->t_lsp_refresh[level - 1]); |
THREAD_TIMER_OFF (area->t_lsp_refresh[level - 1]); |
|
area->lsp_regenerate_pending[level - 1] = 0; |
if (level == IS_LEVEL_1) |
if (level == IS_LEVEL_1) |
THREAD_TIMER_ON (master, area->t_lsp_refresh[level - 1], |
THREAD_TIMER_ON (master, area->t_lsp_refresh[level - 1], |
lsp_l1_refresh, area, refresh_time); |
lsp_l1_refresh, area, refresh_time); |
Line 1621 lsp_generate (struct isis_area *area, int level)
|
Line 1852 lsp_generate (struct isis_area *area, int level)
|
ntohs (newlsp->lsp_header->rem_lifetime), |
ntohs (newlsp->lsp_header->rem_lifetime), |
refresh_time); |
refresh_time); |
} |
} |
|
sched_debug("ISIS (%s): Built L%d LSP. Set triggered regenerate to non-pending.", |
|
area->area_tag, level); |
|
|
return ISIS_OK; |
return ISIS_OK; |
} |
} |
Line 1631 lsp_generate (struct isis_area *area, int level)
|
Line 1864 lsp_generate (struct isis_area *area, int level)
|
static int |
static int |
lsp_regenerate (struct isis_area *area, int level) |
lsp_regenerate (struct isis_area *area, int level) |
{ |
{ |
dict_t *lspdb = area->lspdb[level - 1]; | dict_t *lspdb; |
struct isis_lsp *lsp, *frag; |
struct isis_lsp *lsp, *frag; |
struct listnode *node; |
struct listnode *node; |
u_char lspid[ISIS_SYS_ID_LEN + 2]; |
u_char lspid[ISIS_SYS_ID_LEN + 2]; |
Line 1640 lsp_regenerate (struct isis_area *area, int level)
|
Line 1873 lsp_regenerate (struct isis_area *area, int level)
|
if ((area == NULL) || (area->is_type & level) != level) |
if ((area == NULL) || (area->is_type & level) != level) |
return ISIS_ERROR; |
return ISIS_ERROR; |
|
|
|
lspdb = area->lspdb[level - 1]; |
|
|
memset (lspid, 0, ISIS_SYS_ID_LEN + 2); |
memset (lspid, 0, ISIS_SYS_ID_LEN + 2); |
memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN); |
memcpy (lspid, isis->sysid, ISIS_SYS_ID_LEN); |
|
|
Line 1654 lsp_regenerate (struct isis_area *area, int level)
|
Line 1889 lsp_regenerate (struct isis_area *area, int level)
|
|
|
lsp_clear_data (lsp); |
lsp_clear_data (lsp); |
lsp_build (lsp, area); |
lsp_build (lsp, area); |
lsp->lsp_header->lsp_bits = lsp_bits_generate (level, area->overload_bit); | lsp->lsp_header->lsp_bits = lsp_bits_generate (level, area->overload_bit, |
| area->attached_bit); |
rem_lifetime = lsp_rem_lifetime (area, level); |
rem_lifetime = lsp_rem_lifetime (area, level); |
lsp->lsp_header->rem_lifetime = htons (rem_lifetime); |
lsp->lsp_header->rem_lifetime = htons (rem_lifetime); |
lsp_seqnum_update (lsp); |
lsp_seqnum_update (lsp); |
Line 1664 lsp_regenerate (struct isis_area *area, int level)
|
Line 1900 lsp_regenerate (struct isis_area *area, int level)
|
for (ALL_LIST_ELEMENTS_RO (lsp->lspu.frags, node, frag)) |
for (ALL_LIST_ELEMENTS_RO (lsp->lspu.frags, node, frag)) |
{ |
{ |
frag->lsp_header->lsp_bits = lsp_bits_generate (level, |
frag->lsp_header->lsp_bits = lsp_bits_generate (level, |
area->overload_bit); | area->overload_bit, |
| area->attached_bit); |
/* Set the lifetime values of all the fragments to the same value, |
/* Set the lifetime values of all the fragments to the same value, |
* so that no fragment expires before the lsp is refreshed. |
* so that no fragment expires before the lsp is refreshed. |
*/ |
*/ |
Line 1679 lsp_regenerate (struct isis_area *area, int level)
|
Line 1916 lsp_regenerate (struct isis_area *area, int level)
|
else if (level == IS_LEVEL_2) |
else if (level == IS_LEVEL_2) |
THREAD_TIMER_ON (master, area->t_lsp_refresh[level - 1], |
THREAD_TIMER_ON (master, area->t_lsp_refresh[level - 1], |
lsp_l2_refresh, area, refresh_time); |
lsp_l2_refresh, area, refresh_time); |
|
area->lsp_regenerate_pending[level - 1] = 0; |
|
|
if (isis->debugs & DEBUG_UPDATE_PACKETS) |
if (isis->debugs & DEBUG_UPDATE_PACKETS) |
{ |
{ |
Line 1692 lsp_regenerate (struct isis_area *area, int level)
|
Line 1930 lsp_regenerate (struct isis_area *area, int level)
|
ntohs (lsp->lsp_header->rem_lifetime), |
ntohs (lsp->lsp_header->rem_lifetime), |
refresh_time); |
refresh_time); |
} |
} |
|
sched_debug("ISIS (%s): Rebuilt L%d LSP. Set triggered regenerate to non-pending.", |
|
area->area_tag, level); |
|
|
return ISIS_OK; |
return ISIS_OK; |
} |
} |
Line 1713 lsp_l1_refresh (struct thread *thread)
|
Line 1953 lsp_l1_refresh (struct thread *thread)
|
if ((area->is_type & IS_LEVEL_1) == 0) |
if ((area->is_type & IS_LEVEL_1) == 0) |
return ISIS_ERROR; |
return ISIS_ERROR; |
|
|
|
sched_debug("ISIS (%s): LSP L1 refresh timer expired. Refreshing LSP...", area->area_tag); |
return lsp_regenerate (area, IS_LEVEL_1); |
return lsp_regenerate (area, IS_LEVEL_1); |
} |
} |
|
|
Line 1730 lsp_l2_refresh (struct thread *thread)
|
Line 1971 lsp_l2_refresh (struct thread *thread)
|
if ((area->is_type & IS_LEVEL_2) == 0) |
if ((area->is_type & IS_LEVEL_2) == 0) |
return ISIS_ERROR; |
return ISIS_ERROR; |
|
|
|
sched_debug("ISIS (%s): LSP L2 refresh timer expired. Refreshing LSP...", area->area_tag); |
return lsp_regenerate (area, IS_LEVEL_2); |
return lsp_regenerate (area, IS_LEVEL_2); |
} |
} |
|
|
Line 1739 lsp_regenerate_schedule (struct isis_area *area, int l
|
Line 1981 lsp_regenerate_schedule (struct isis_area *area, int l
|
struct isis_lsp *lsp; |
struct isis_lsp *lsp; |
u_char id[ISIS_SYS_ID_LEN + 2]; |
u_char id[ISIS_SYS_ID_LEN + 2]; |
time_t now, diff; |
time_t now, diff; |
|
long timeout; |
struct listnode *cnode; |
struct listnode *cnode; |
struct isis_circuit *circuit; |
struct isis_circuit *circuit; |
int lvl; |
int lvl; |
Line 1746 lsp_regenerate_schedule (struct isis_area *area, int l
|
Line 1989 lsp_regenerate_schedule (struct isis_area *area, int l
|
if (area == NULL) |
if (area == NULL) |
return ISIS_ERROR; |
return ISIS_ERROR; |
|
|
|
sched_debug("ISIS (%s): Scheduling regeneration of %s LSPs, %sincluding PSNs", |
|
area->area_tag, circuit_t2string(level), all_pseudo ? "" : "not "); |
|
|
memcpy (id, isis->sysid, ISIS_SYS_ID_LEN); |
memcpy (id, isis->sysid, ISIS_SYS_ID_LEN); |
LSP_PSEUDO_ID (id) = LSP_FRAGMENT (id) = 0; |
LSP_PSEUDO_ID (id) = LSP_FRAGMENT (id) = 0; |
now = time (NULL); |
now = time (NULL); |
Line 1755 lsp_regenerate_schedule (struct isis_area *area, int l
|
Line 2001 lsp_regenerate_schedule (struct isis_area *area, int l
|
if (!((level & lvl) && (area->is_type & lvl))) |
if (!((level & lvl) && (area->is_type & lvl))) |
continue; |
continue; |
|
|
|
sched_debug("ISIS (%s): Checking whether L%d needs to be scheduled", |
|
area->area_tag, lvl); |
|
|
if (area->lsp_regenerate_pending[lvl - 1]) |
if (area->lsp_regenerate_pending[lvl - 1]) |
continue; | { |
| struct timeval remain = thread_timer_remain(area->t_lsp_refresh[lvl - 1]); |
| sched_debug("ISIS (%s): Regeneration is already pending, nothing todo." |
| " (Due in %lld.%03lld seconds)", area->area_tag, |
| (long long)remain.tv_sec, (long long)remain.tv_usec / 1000); |
| continue; |
| } |
|
|
lsp = lsp_search (id, area->lspdb[lvl - 1]); |
lsp = lsp_search (id, area->lspdb[lvl - 1]); |
if (!lsp) |
if (!lsp) |
continue; | { |
| sched_debug("ISIS (%s): We do not have any LSPs to regenerate, nothing todo.", |
| area->area_tag); |
| continue; |
| } |
|
|
/* |
/* |
* Throttle avoidance |
* Throttle avoidance |
*/ |
*/ |
|
sched_debug("ISIS (%s): Will schedule regen timer. Last run was: %lld, Now is: %lld", |
|
area->area_tag, (long long)lsp->last_generated, (long long)now); |
THREAD_TIMER_OFF (area->t_lsp_refresh[lvl - 1]); |
THREAD_TIMER_OFF (area->t_lsp_refresh[lvl - 1]); |
diff = now - lsp->last_generated; |
diff = now - lsp->last_generated; |
if (diff < area->lsp_gen_interval[lvl - 1]) |
if (diff < area->lsp_gen_interval[lvl - 1]) |
{ |
{ |
area->lsp_regenerate_pending[lvl - 1] = 1; | timeout = 1000 * (area->lsp_gen_interval[lvl - 1] - diff); |
if (lvl == IS_LEVEL_1) | sched_debug("ISIS (%s): Scheduling in %ld ms to match configured lsp_gen_interval", |
THREAD_TIMER_ON (master, area->t_lsp_refresh[lvl - 1], | area->area_tag, timeout); |
lsp_l1_refresh, area, | |
area->lsp_gen_interval[lvl - 1] - diff); | |
else if (lvl == IS_LEVEL_2) | |
THREAD_TIMER_ON (master, area->t_lsp_refresh[lvl - 1], | |
lsp_l2_refresh, area, | |
area->lsp_gen_interval[lvl - 1] - diff); | |
} |
} |
else |
else |
{ |
{ |
lsp_regenerate (area, lvl); | /* |
| * lsps are not regenerated if lsp_regenerate function is called |
| * directly. However if the lsp_regenerate call is queued for |
| * later execution it works. |
| */ |
| timeout = 100; |
| sched_debug("ISIS (%s): Last generation was more than lsp_gen_interval ago." |
| " Scheduling for execution in %ld ms.", area->area_tag, timeout); |
} |
} |
|
|
|
area->lsp_regenerate_pending[lvl - 1] = 1; |
|
if (lvl == IS_LEVEL_1) |
|
{ |
|
THREAD_TIMER_MSEC_ON(master, area->t_lsp_refresh[lvl - 1], |
|
lsp_l1_refresh, area, timeout); |
|
} |
|
else if (lvl == IS_LEVEL_2) |
|
{ |
|
THREAD_TIMER_MSEC_ON(master, area->t_lsp_refresh[lvl - 1], |
|
lsp_l2_refresh, area, timeout); |
|
} |
} |
} |
|
|
if (all_pseudo) |
if (all_pseudo) |
Line 1811 lsp_build_pseudo (struct isis_lsp *lsp, struct isis_ci
|
Line 2085 lsp_build_pseudo (struct isis_lsp *lsp, struct isis_ci
|
struct es_neigh *es_neigh; |
struct es_neigh *es_neigh; |
struct list *adj_list; |
struct list *adj_list; |
struct listnode *node; |
struct listnode *node; |
|
struct isis_area *area = circuit->area; |
|
|
|
lsp_debug("ISIS (%s): Constructing pseudo LSP %s for interface %s level %d", |
|
area->area_tag, rawlspid_print(lsp->lsp_header->lsp_id), |
|
circuit->interface->name, level); |
|
|
lsp->level = level; |
lsp->level = 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_header->lsp_bits = lsp_bits_generate (level, 0); | lsp->lsp_header->lsp_bits = lsp_bits_generate (level, 0, |
| circuit->area->attached_bit); |
|
|
/* |
/* |
* add self to IS neighbours |
* add self to IS neighbours |
Line 1830 lsp_build_pseudo (struct isis_lsp *lsp, struct isis_ci
|
Line 2110 lsp_build_pseudo (struct isis_lsp *lsp, struct isis_ci
|
|
|
memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN); |
memcpy (&is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN); |
listnode_add (lsp->tlv_data.is_neighs, is_neigh); |
listnode_add (lsp->tlv_data.is_neighs, is_neigh); |
|
lsp_debug("ISIS (%s): Adding %s.%02x as old-style neighbor (self)", |
|
area->area_tag, sysid_print(is_neigh->neigh_id), |
|
LSP_PSEUDO_ID(is_neigh->neigh_id)); |
} |
} |
if (circuit->area->newmetric) |
if (circuit->area->newmetric) |
{ |
{ |
Line 1842 lsp_build_pseudo (struct isis_lsp *lsp, struct isis_ci
|
Line 2125 lsp_build_pseudo (struct isis_lsp *lsp, struct isis_ci
|
|
|
memcpy (&te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN); |
memcpy (&te_is_neigh->neigh_id, isis->sysid, ISIS_SYS_ID_LEN); |
listnode_add (lsp->tlv_data.te_is_neighs, te_is_neigh); |
listnode_add (lsp->tlv_data.te_is_neighs, te_is_neigh); |
|
lsp_debug("ISIS (%s): Adding %s.%02x as te-style neighbor (self)", |
|
area->area_tag, sysid_print(te_is_neigh->neigh_id), |
|
LSP_PSEUDO_ID(te_is_neigh->neigh_id)); |
} |
} |
|
|
adj_list = list_new (); |
adj_list = list_new (); |
Line 1863 lsp_build_pseudo (struct isis_lsp *lsp, struct isis_ci
|
Line 2149 lsp_build_pseudo (struct isis_lsp *lsp, struct isis_ci
|
|
|
memcpy (&is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN); |
memcpy (&is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN); |
listnode_add (lsp->tlv_data.is_neighs, is_neigh); |
listnode_add (lsp->tlv_data.is_neighs, is_neigh); |
|
lsp_debug("ISIS (%s): Adding %s.%02x as old-style neighbor (peer)", |
|
area->area_tag, sysid_print(is_neigh->neigh_id), |
|
LSP_PSEUDO_ID(is_neigh->neigh_id)); |
} |
} |
if (circuit->area->newmetric) |
if (circuit->area->newmetric) |
{ |
{ |
Line 1870 lsp_build_pseudo (struct isis_lsp *lsp, struct isis_ci
|
Line 2159 lsp_build_pseudo (struct isis_lsp *lsp, struct isis_ci
|
sizeof (struct te_is_neigh)); |
sizeof (struct te_is_neigh)); |
memcpy (&te_is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN); |
memcpy (&te_is_neigh->neigh_id, adj->sysid, ISIS_SYS_ID_LEN); |
listnode_add (lsp->tlv_data.te_is_neighs, te_is_neigh); |
listnode_add (lsp->tlv_data.te_is_neighs, te_is_neigh); |
|
lsp_debug("ISIS (%s): Adding %s.%02x as te-style neighbor (peer)", |
|
area->area_tag, sysid_print(te_is_neigh->neigh_id), |
|
LSP_PSEUDO_ID(te_is_neigh->neigh_id)); |
} |
} |
} |
} |
else if (level == IS_LEVEL_1 && adj->sys_type == ISIS_SYSTYPE_ES) |
else if (level == IS_LEVEL_1 && adj->sys_type == ISIS_SYSTYPE_ES) |
Line 1885 lsp_build_pseudo (struct isis_lsp *lsp, struct isis_ci
|
Line 2177 lsp_build_pseudo (struct isis_lsp *lsp, struct isis_ci
|
|
|
memcpy (&es_neigh->first_es_neigh, adj->sysid, ISIS_SYS_ID_LEN); |
memcpy (&es_neigh->first_es_neigh, adj->sysid, ISIS_SYS_ID_LEN); |
listnode_add (lsp->tlv_data.es_neighs, es_neigh); |
listnode_add (lsp->tlv_data.es_neighs, es_neigh); |
|
lsp_debug("ISIS (%s): Adding %s as ES neighbor (peer)", |
|
area->area_tag, sysid_print(es_neigh->first_es_neigh)); |
} |
} |
|
else |
|
{ |
|
lsp_debug("ISIS (%s): Ignoring neighbor %s, level does not match", |
|
area->area_tag, sysid_print(adj->sysid)); |
|
} |
} |
} |
|
else |
|
{ |
|
lsp_debug("ISIS (%s): Ignoring neighbor %s, level does not intersect", |
|
area->area_tag, sysid_print(adj->sysid)); |
|
} |
} |
} |
list_delete (adj_list); |
list_delete (adj_list); |
|
|
|
lsp_debug("ISIS (%s): Pseudo LSP construction is complete.", area->area_tag); |
|
|
/* Reset endp of stream to overwrite only TLV part of it. */ |
/* Reset endp of stream to overwrite only TLV part of it. */ |
stream_reset (lsp->pdu); |
stream_reset (lsp->pdu); |
stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); |
stream_forward_endp (lsp->pdu, ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN); |
Line 1944 lsp_generate_pseudo (struct isis_circuit *circuit, int
|
Line 2250 lsp_generate_pseudo (struct isis_circuit *circuit, int
|
|
|
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, circuit->area->is_type, 0, level); | lsp = lsp_new (circuit->area, lsp_id, rem_lifetime, 1, |
| circuit->area->is_type | circuit->area->attached_bit, |
| 0, level); |
lsp->area = circuit->area; |
lsp->area = circuit->area; |
|
|
lsp_build_pseudo (lsp, circuit, level); |
lsp_build_pseudo (lsp, circuit, level); |
Line 2010 lsp_regenerate_pseudo (struct isis_circuit *circuit, i
|
Line 2318 lsp_regenerate_pseudo (struct isis_circuit *circuit, i
|
lsp_build_pseudo (lsp, circuit, level); |
lsp_build_pseudo (lsp, circuit, 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_header->lsp_bits = lsp_bits_generate (level, 0); | lsp->lsp_header->lsp_bits = lsp_bits_generate (level, 0, |
| circuit->area->attached_bit); |
rem_lifetime = lsp_rem_lifetime (circuit->area, level); |
rem_lifetime = lsp_rem_lifetime (circuit->area, level); |
lsp->lsp_header->rem_lifetime = htons (rem_lifetime); |
lsp->lsp_header->rem_lifetime = htons (rem_lifetime); |
lsp_inc_seqnum (lsp, 0); |
lsp_inc_seqnum (lsp, 0); |
Line 2098 lsp_regenerate_schedule_pseudo (struct isis_circuit *c
|
Line 2407 lsp_regenerate_schedule_pseudo (struct isis_circuit *c
|
struct isis_lsp *lsp; |
struct isis_lsp *lsp; |
u_char lsp_id[ISIS_SYS_ID_LEN + 2]; |
u_char lsp_id[ISIS_SYS_ID_LEN + 2]; |
time_t now, diff; |
time_t now, diff; |
|
long timeout; |
int lvl; |
int lvl; |
|
struct isis_area *area = circuit->area; |
|
|
if (circuit == NULL || |
if (circuit == NULL || |
circuit->circ_type != CIRCUIT_T_BROADCAST || |
circuit->circ_type != CIRCUIT_T_BROADCAST || |
circuit->state != C_STATE_UP) |
circuit->state != C_STATE_UP) |
return ISIS_OK; |
return ISIS_OK; |
|
|
|
sched_debug("ISIS (%s): Scheduling regeneration of %s pseudo LSP for interface %s", |
|
area->area_tag, circuit_t2string(level), circuit->interface->name); |
|
|
memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN); |
memcpy (lsp_id, isis->sysid, ISIS_SYS_ID_LEN); |
LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id; |
LSP_PSEUDO_ID (lsp_id) = circuit->circuit_id; |
LSP_FRAGMENT (lsp_id) = 0; |
LSP_FRAGMENT (lsp_id) = 0; |
Line 2112 lsp_regenerate_schedule_pseudo (struct isis_circuit *c
|
Line 2426 lsp_regenerate_schedule_pseudo (struct isis_circuit *c
|
|
|
for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) |
for (lvl = IS_LEVEL_1; lvl <= IS_LEVEL_2; lvl++) |
{ |
{ |
|
sched_debug("ISIS (%s): Checking whether L%d pseudo LSP needs to be scheduled", |
|
area->area_tag, lvl); |
|
|
if (!((level & lvl) && (circuit->is_type & lvl))) |
if (!((level & lvl) && (circuit->is_type & lvl))) |
continue; | { |
| sched_debug("ISIS (%s): Level is not active on circuit", |
| area->area_tag); |
| continue; |
| } |
|
|
if (circuit->u.bc.is_dr[lvl - 1] == 0 || | if (circuit->u.bc.is_dr[lvl - 1] == 0) |
circuit->lsp_regenerate_pending[lvl - 1]) | { |
continue; | sched_debug("ISIS (%s): This IS is not DR, nothing to do.", |
| area->area_tag); |
| continue; |
| } |
|
|
|
if (circuit->lsp_regenerate_pending[lvl - 1]) |
|
{ |
|
struct timeval remain = |
|
thread_timer_remain(circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]); |
|
sched_debug("ISIS (%s): Regenerate is already pending, nothing todo." |
|
" (Due in %lld.%03lld seconds)", area->area_tag, |
|
(long long)remain.tv_sec, (long long)remain.tv_usec/1000); |
|
continue; |
|
} |
|
|
lsp = lsp_search (lsp_id, circuit->area->lspdb[lvl - 1]); |
lsp = lsp_search (lsp_id, circuit->area->lspdb[lvl - 1]); |
if (!lsp) |
if (!lsp) |
continue; | { |
| sched_debug("ISIS (%s): Pseudonode LSP does not exist yet, nothing to regenerate.", |
| area->area_tag); |
| continue; |
| } |
|
|
/* |
/* |
* Throttle avoidance |
* Throttle avoidance |
*/ |
*/ |
|
sched_debug("ISIS (%s): Will schedule PSN regen timer. Last run was: %lld, Now is: %lld", |
|
area->area_tag, (long long)lsp->last_generated, (long long) now); |
THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]); |
THREAD_TIMER_OFF (circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1]); |
diff = now - lsp->last_generated; |
diff = now - lsp->last_generated; |
if (diff < circuit->area->lsp_gen_interval[lvl - 1]) |
if (diff < circuit->area->lsp_gen_interval[lvl - 1]) |
{ |
{ |
circuit->lsp_regenerate_pending[lvl - 1] = 1; | timeout = 1000 * (circuit->area->lsp_gen_interval[lvl - 1] - diff); |
if (lvl == IS_LEVEL_1) | sched_debug("ISIS (%s): Sechduling in %ld ms to match configured lsp_gen_interval", |
THREAD_TIMER_ON (master, | area->area_tag, timeout); |
circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1], | |
lsp_l1_refresh_pseudo, circuit, | |
circuit->area->lsp_gen_interval[lvl - 1] - diff); | |
else if (lvl == IS_LEVEL_2) | |
THREAD_TIMER_ON (master, | |
circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1], | |
lsp_l2_refresh_pseudo, circuit, | |
circuit->area->lsp_gen_interval[lvl - 1] - diff); | |
} |
} |
else |
else |
{ |
{ |
lsp_regenerate_pseudo (circuit, lvl); | timeout = 100; |
| sched_debug("ISIS (%s): Last generation was more than lsp_gen_interval ago." |
| " Scheduling for execution in %ld ms.", area->area_tag, timeout); |
} |
} |
|
|
|
circuit->lsp_regenerate_pending[lvl - 1] = 1; |
|
|
|
if (lvl == IS_LEVEL_1) |
|
{ |
|
THREAD_TIMER_MSEC_ON(master, |
|
circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1], |
|
lsp_l1_refresh_pseudo, circuit, timeout); |
|
} |
|
else if (lvl == IS_LEVEL_2) |
|
{ |
|
THREAD_TIMER_MSEC_ON(master, |
|
circuit->u.bc.t_refresh_pseudo_lsp[lvl - 1], |
|
lsp_l2_refresh_pseudo, circuit, timeout); |
|
} |
} |
} |
|
|
return ISIS_OK; |
return ISIS_OK; |
Line 2319 lsp_purge_pseudo (u_char * id, struct isis_circuit *ci
|
Line 2668 lsp_purge_pseudo (u_char * id, struct isis_circuit *ci
|
* -> Do as in 7.3.16.4 |
* -> Do as in 7.3.16.4 |
*/ |
*/ |
void |
void |
lsp_purge_non_exist (struct isis_link_state_hdr *lsp_hdr, | lsp_purge_non_exist (int level, |
| struct isis_link_state_hdr *lsp_hdr, |
struct isis_area *area) |
struct isis_area *area) |
{ |
{ |
struct isis_lsp *lsp; |
struct isis_lsp *lsp; |
Line 2329 lsp_purge_non_exist (struct isis_link_state_hdr *lsp_h
|
Line 2679 lsp_purge_non_exist (struct isis_link_state_hdr *lsp_h
|
*/ |
*/ |
lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp)); |
lsp = XCALLOC (MTYPE_ISIS_LSP, sizeof (struct isis_lsp)); |
lsp->area = area; |
lsp->area = area; |
lsp->level = ((lsp_hdr->lsp_bits & LSPBIT_IST) == IS_LEVEL_1) ? | lsp->level = level; |
IS_LEVEL_1 : IS_LEVEL_2; | lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu); |
/* FIXME: Should be minimal 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); |
Line 2394 static int
|
Line 2742 static int
|
top_lsp_refresh (struct thread *thread) |
top_lsp_refresh (struct thread *thread) |
{ |
{ |
struct isis_lsp *lsp; |
struct isis_lsp *lsp; |
u_int16_t rem_lifetime, refresh_time; | u_int16_t rem_lifetime; |
|
|
lsp = THREAD_ARG (thread); |
lsp = THREAD_ARG (thread); |
assert (lsp); |
assert (lsp); |
Line 2413 top_lsp_refresh (struct thread *thread)
|
Line 2761 top_lsp_refresh (struct thread *thread)
|
isis_dynhn_insert (lsp->lsp_header->lsp_id, lsp->tlv_data.hostname, |
isis_dynhn_insert (lsp->lsp_header->lsp_id, lsp->tlv_data.hostname, |
IS_LEVEL_1); |
IS_LEVEL_1); |
|
|
lsp->lsp_header->lsp_bits = lsp_bits_generate (level, | lsp->lsp_header->lsp_bits = lsp_bits_generate (lsp->level, |
lsp->area->overload_bit); | lsp->area->overload_bit, |
| lsp->area->attached_bit); |
rem_lifetime = lsp_rem_lifetime (lsp->area, IS_LEVEL_1); |
rem_lifetime = lsp_rem_lifetime (lsp->area, IS_LEVEL_1); |
lsp->lsp_header->rem_lifetime = htons (rem_lifetime); |
lsp->lsp_header->rem_lifetime = htons (rem_lifetime); |
|
|
refresh_time = lsp_refresh_time (lsp, rem_lifetime); | /* refresh_time = lsp_refresh_time (lsp, rem_lifetime); */ |
THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp, |
THREAD_TIMER_ON (master, lsp->t_lsp_top_ref, top_lsp_refresh, lsp, |
lsp->area->lsp_refresh[0]); |
lsp->area->lsp_refresh[0]); |
|
|
Line 2453 generate_topology_lsps (struct isis_area *area)
|
Line 2802 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, |
| IS_LEVEL_1 | area->overload_bit | area->attached_bit, |
0, 1); |
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. */ |