Merge pull request #854 from opensourcerouting/isis-parser

IS-IS: rewrite TLV deserializer/serializer
This commit is contained in:
Donald Sharp 2017-08-03 06:46:00 -04:00 committed by GitHub
commit 28ae32e66e
43 changed files with 5707 additions and 6017 deletions

View File

@ -8,24 +8,26 @@ LIBS = @LIBS@
AM_CFLAGS = $(WERROR)
noinst_LIBRARIES = libisis.a
sbin_PROGRAMS = isisd
sbin_PROGRAMS = isisd
libisis_a_SOURCES = \
isis_memory.c \
isis_adjacency.c isis_lsp.c dict.c isis_circuit.c isis_pdu.c \
isis_tlv.c isisd.c isis_misc.c isis_zebra.c isis_dr.c \
isisd.c isis_misc.c isis_zebra.c isis_dr.c \
isis_flags.c isis_dynhn.c iso_checksum.c isis_csm.c isis_events.c \
isis_spf.c isis_redist.c isis_route.c isis_routemap.c isis_te.c \
isis_vty.c isis_mt.c
isis_vty.c isis_mt.c \
isis_tlvs.c
noinst_HEADERS = \
isis_memory.h \
isisd.h isis_pdu.h isis_tlv.h isis_adjacency.h isis_constants.h \
isisd.h isis_pdu.h isis_adjacency.h isis_constants.h \
isis_lsp.h dict.h isis_circuit.h isis_misc.h isis_network.h \
isis_zebra.h isis_dr.h isis_flags.h isis_dynhn.h isis_common.h \
iso_checksum.h isis_csm.h isis_events.h isis_spf.h isis_redist.h \
isis_route.h isis_routemap.h isis_te.h isis_mt.h
isis_route.h isis_routemap.h isis_te.h isis_mt.h \
isis_tlvs.h
isisd_SOURCES = \
isis_main.c $(libisis_a_SOURCES) \

View File

@ -43,7 +43,6 @@
#include "isisd/isis_dr.h"
#include "isisd/isis_dynhn.h"
#include "isisd/isis_pdu.h"
#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_spf.h"
#include "isisd/isis_events.h"
@ -69,11 +68,6 @@ struct isis_adjacency *isis_new_adj(const u_char *id, const u_char *snpa,
adj = adj_alloc(id); /* P2P kludge */
if (adj == NULL) {
zlog_err("Out of memory!");
return NULL;
}
if (snpa) {
memcpy(adj->snpa, snpa, ETH_ALEN);
} else {
@ -137,12 +131,12 @@ void isis_delete_adj(void *arg)
/* remove from SPF trees */
spftree_area_adj_del(adj->circuit->area, adj);
if (adj->area_addrs)
list_delete(adj->area_addrs);
if (adj->ipv4_addrs)
list_delete(adj->ipv4_addrs);
if (adj->ipv6_addrs)
list_delete(adj->ipv6_addrs);
if (adj->area_addresses)
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses);
if (adj->ipv4_addresses)
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv4_addresses);
if (adj->ipv6_addresses)
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses);
adj_mt_finish(adj);
@ -192,7 +186,7 @@ void isis_adj_state_change(struct isis_adjacency *adj,
dyn = dynhn_find_by_id(adj->sysid);
if (dyn)
adj_name = (const char *)dyn->name.name;
adj_name = dyn->hostname;
else
adj_name = sysid_print(adj->sysid);
@ -301,33 +295,29 @@ void isis_adj_state_change(struct isis_adjacency *adj,
void isis_adj_print(struct isis_adjacency *adj)
{
struct isis_dynhn *dyn;
struct listnode *node;
struct in_addr *ipv4_addr;
struct in6_addr *ipv6_addr;
u_char ip6[INET6_ADDRSTRLEN];
if (!adj)
return;
dyn = dynhn_find_by_id(adj->sysid);
if (dyn)
zlog_debug("%s", dyn->name.name);
zlog_debug("%s", dyn->hostname);
zlog_debug("SystemId %20s SNPA %s, level %d\nHolding Time %d",
sysid_print(adj->sysid), snpa_print(adj->snpa), adj->level,
adj->hold_time);
if (adj->ipv4_addrs && listcount(adj->ipv4_addrs) > 0) {
if (adj->ipv4_address_count) {
zlog_debug("IPv4 Address(es):");
for (ALL_LIST_ELEMENTS_RO(adj->ipv4_addrs, node, ipv4_addr))
zlog_debug("%s", inet_ntoa(*ipv4_addr));
for (unsigned int i = 0; i < adj->ipv4_address_count; i++)
zlog_debug("%s", inet_ntoa(adj->ipv4_addresses[i]));
}
if (adj->ipv6_addrs && listcount(adj->ipv6_addrs) > 0) {
if (adj->ipv6_address_count) {
zlog_debug("IPv6 Address(es):");
for (ALL_LIST_ELEMENTS_RO(adj->ipv6_addrs, node, ipv6_addr)) {
inet_ntop(AF_INET6, ipv6_addr, (char *)ip6,
INET6_ADDRSTRLEN);
zlog_debug("%s", ip6);
for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
char buf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &adj->ipv6_addresses[i], buf,
sizeof(buf));
zlog_debug("%s", buf);
}
}
zlog_debug("Speaks: %s", nlpid2string(&adj->nlpids));
@ -358,17 +348,13 @@ int isis_adj_expire(struct thread *thread)
void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
char detail)
{
struct in6_addr *ipv6_addr;
u_char ip6[INET6_ADDRSTRLEN];
struct in_addr *ip_addr;
time_t now;
struct isis_dynhn *dyn;
int level;
struct listnode *node;
dyn = dynhn_find_by_id(adj->sysid);
if (dyn)
vty_out(vty, " %-20s", dyn->name.name);
vty_out(vty, " %-20s", dyn->hostname);
else
vty_out(vty, " %-20s", sysid_print(adj->sysid));
@ -429,8 +415,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
&& (adj->circuit->circ_type == CIRCUIT_T_BROADCAST)) {
dyn = dynhn_find_by_id(adj->lanid);
if (dyn)
vty_out(vty, ", LAN id: %s.%02x",
dyn->name.name,
vty_out(vty, ", LAN id: %s.%02x", dyn->hostname,
adj->lanid[ISIS_SYS_ID_LEN]);
else
vty_out(vty, ", LAN id: %s.%02x",
@ -452,28 +437,32 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
}
vty_out(vty, "\n");
if (adj->area_addrs && listcount(adj->area_addrs) > 0) {
struct area_addr *area_addr;
if (adj->area_address_count) {
vty_out(vty, " Area Address(es):\n");
for (ALL_LIST_ELEMENTS_RO(adj->area_addrs, node,
area_addr))
for (unsigned int i = 0; i < adj->area_address_count;
i++) {
vty_out(vty, " %s\n",
isonet_print(area_addr->area_addr,
area_addr->addr_len));
isonet_print(adj->area_addresses[i]
.area_addr,
adj->area_addresses[i]
.addr_len));
}
}
if (adj->ipv4_addrs && listcount(adj->ipv4_addrs) > 0) {
if (adj->ipv4_address_count) {
vty_out(vty, " IPv4 Address(es):\n");
for (ALL_LIST_ELEMENTS_RO(adj->ipv4_addrs, node,
ip_addr))
vty_out(vty, " %s\n", inet_ntoa(*ip_addr));
for (unsigned int i = 0; i < adj->ipv4_address_count;
i++)
vty_out(vty, " %s\n",
inet_ntoa(adj->ipv4_addresses[i]));
}
if (adj->ipv6_addrs && listcount(adj->ipv6_addrs) > 0) {
if (adj->ipv6_address_count) {
vty_out(vty, " IPv6 Address(es):\n");
for (ALL_LIST_ELEMENTS_RO(adj->ipv6_addrs, node,
ipv6_addr)) {
inet_ntop(AF_INET6, ipv6_addr, (char *)ip6,
INET6_ADDRSTRLEN);
vty_out(vty, " %s\n", ip6);
for (unsigned int i = 0; i < adj->ipv6_address_count;
i++) {
char buf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &adj->ipv6_addresses[i],
buf, sizeof(buf));
vty_out(vty, " %s\n", buf);
}
}
vty_out(vty, "\n");

View File

@ -73,13 +73,16 @@ struct isis_adjacency {
int dischanges[ISIS_LEVELS]; /* how many DIS changes ? */
/* an array of N levels for M records */
struct isis_dis_record dis_record[DIS_RECORDS * ISIS_LEVELS];
enum isis_adj_state adj_state; /* adjacencyState */
enum isis_adj_usage adj_usage; /* adjacencyUsage */
struct list *area_addrs; /* areaAdressesOfNeighbour */
struct nlpids nlpids; /* protocols spoken ... */
struct list *ipv4_addrs;
enum isis_adj_state adj_state; /* adjacencyState */
enum isis_adj_usage adj_usage; /* adjacencyUsage */
struct area_addr *area_addresses; /* areaAdressesOfNeighbour */
unsigned int area_address_count;
struct nlpids nlpids; /* protocols spoken ... */
struct in_addr *ipv4_addresses;
unsigned int ipv4_address_count;
struct in_addr router_address;
struct list *ipv6_addrs;
struct in6_addr *ipv6_addresses;
unsigned int ipv6_address_count;
struct in6_addr router_address6;
u_char prio[ISIS_LEVELS]; /* priorityOfNeighbour for DIS */
int circuit_t; /* from hello PDU hdr */

View File

@ -48,7 +48,6 @@
#include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_pdu.h"
#include "isisd/isis_network.h"

View File

@ -46,16 +46,6 @@ struct isis_passwd {
u_char passwd[255];
};
/*
* (Dynamic) Hostname
* one struct for cache list
* one struct for LSP TLV
*/
struct hostname {
u_char namelen;
u_char name[255];
};
/*
* Supported Protocol IDs
*/

View File

@ -37,7 +37,6 @@
#include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_pdu.h"
#include "isisd/isis_network.h"

View File

@ -42,7 +42,6 @@
#include "isisd/isis_adjacency.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_pdu.h"
#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_dr.h"
#include "isisd/isis_events.h"

View File

@ -94,38 +94,26 @@ struct isis_dynhn *dynhn_find_by_name(const char *hostname)
struct isis_dynhn *dyn = NULL;
for (ALL_LIST_ELEMENTS_RO(dyn_cache, node, dyn))
if (strncmp((char *)dyn->name.name, hostname, 255) == 0)
if (strncmp(dyn->hostname, hostname, 255) == 0)
return dyn;
return NULL;
}
void isis_dynhn_insert(const u_char *id, struct hostname *hostname, int level)
void isis_dynhn_insert(const u_char *id, const char *hostname, int level)
{
struct isis_dynhn *dyn;
dyn = dynhn_find_by_id(id);
if (dyn) {
memcpy(&dyn->name, hostname, hostname->namelen + 1);
memcpy(dyn->id, id, ISIS_SYS_ID_LEN);
dyn->refresh = time(NULL);
return;
}
dyn = XCALLOC(MTYPE_ISIS_DYNHN, sizeof(struct isis_dynhn));
if (!dyn) {
zlog_warn("isis_dynhn_insert(): out of memory!");
return;
dyn = XCALLOC(MTYPE_ISIS_DYNHN, sizeof(struct isis_dynhn));
memcpy(dyn->id, id, ISIS_SYS_ID_LEN);
dyn->level = level;
listnode_add(dyn_cache, dyn);
}
/* we also copy the length */
memcpy(&dyn->name, hostname, hostname->namelen + 1);
memcpy(dyn->id, id, ISIS_SYS_ID_LEN);
snprintf(dyn->hostname, sizeof(dyn->hostname), "%s", hostname);
dyn->refresh = time(NULL);
dyn->level = level;
listnode_add(dyn_cache, dyn);
return;
}
void isis_dynhn_remove(const u_char *id)
@ -137,7 +125,6 @@ void isis_dynhn_remove(const u_char *id)
return;
listnode_delete(dyn_cache, dyn);
XFREE(MTYPE_ISIS_DYNHN, dyn);
return;
}
/*
@ -155,7 +142,7 @@ void dynhn_print_all(struct vty *vty)
for (ALL_LIST_ELEMENTS_RO(dyn_cache, node, dyn)) {
vty_out(vty, "%-7d", dyn->level);
vty_out(vty, "%-15s%-15s\n", sysid_print(dyn->id),
dyn->name.name);
dyn->hostname);
}
vty_out(vty, " * %s %s\n", sysid_print(isis->sysid),

View File

@ -25,13 +25,13 @@
struct isis_dynhn {
u_char id[ISIS_SYS_ID_LEN];
struct hostname name;
char hostname[256];
time_t refresh;
int level;
};
void dyn_cache_init(void);
void isis_dynhn_insert(const u_char *id, struct hostname *hostname, int level);
void isis_dynhn_insert(const u_char *id, const char *hostname, int level);
void isis_dynhn_remove(const u_char *id);
struct isis_dynhn *dynhn_find_by_id(const u_char *id);
struct isis_dynhn *dynhn_find_by_name(const char *hostname);

View File

@ -37,7 +37,6 @@
#include "isisd/isis_common.h"
#include "isisd/isis_flags.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_pdu.h"
#include "isisd/isis_network.h"

File diff suppressed because it is too large Load Diff

View File

@ -24,19 +24,19 @@
#ifndef _ZEBRA_ISIS_LSP_H
#define _ZEBRA_ISIS_LSP_H
#include "isisd/isis_pdu.h"
/* Structure for isis_lsp, this structure will only support the fixed
* System ID (Currently 6) (atleast for now). In order to support more
* We will have to split the header into two parts, and for readability
* sake it should better be avoided */
struct isis_lsp {
struct isis_fixed_hdr *isis_header; /* normally equals pdu */
struct isis_link_state_hdr *lsp_header; /* pdu + isis_header_len */
struct stream *pdu; /* full pdu lsp */
struct isis_lsp_hdr hdr;
struct stream *pdu; /* full pdu lsp */
union {
struct list *frags;
struct isis_lsp *zero_lsp;
} lspu;
u_int32_t auth_tlv_offset; /* authentication TLV position in the pdu */
u_int32_t SRMflags[ISIS_MAX_CIRCUITS];
u_int32_t SSNflags[ISIS_MAX_CIRCUITS];
int level; /* L1 or L2? */
@ -47,7 +47,7 @@ struct isis_lsp {
/* used for 60 second counting when rem_lifetime is zero */
int age_out;
struct isis_area *area;
struct tlvs tlv_data; /* Simplifies TLV access */
struct isis_tlvs *tlvs;
};
dict_t *lsp_db_init(void);
@ -59,13 +59,13 @@ int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo);
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(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,
u_int16_t pdu_len,
struct isis_lsp *lsp0,
struct isis_area *area, int level);
struct isis_lsp *lsp_new(struct isis_area *area, uint8_t *lsp_id,
uint16_t rem_lifetime, uint32_t seq_num,
uint8_t lsp_bits, uint16_t checksum, int level);
struct isis_lsp *lsp_new_from_recv(struct isis_lsp_hdr *hdr,
struct isis_tlvs *tlvs,
struct stream *stream, struct isis_lsp *lsp0,
struct isis_area *area, int level);
void lsp_insert(struct isis_lsp *lsp, dict_t *lspdb);
struct isis_lsp *lsp_search(u_char *id, dict_t *lspdb);
@ -73,12 +73,9 @@ void lsp_build_list(u_char *start_id, u_char *stop_id, u_char num_lsps,
struct list *list, dict_t *lspdb);
void lsp_build_list_nonzero_ht(u_char *start_id, u_char *stop_id,
struct list *list, dict_t *lspdb);
void lsp_build_list_ssn(struct isis_circuit *circuit, u_char num_lsps,
struct list *list, dict_t *lspdb);
void lsp_search_and_destroy(u_char *id, dict_t *lspdb);
void lsp_purge_pseudo(u_char *id, struct isis_circuit *circuit, int level);
void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr,
void lsp_purge_non_exist(int level, struct isis_lsp_hdr *hdr,
struct isis_area *area);
#define LSP_EQUAL 1
@ -92,16 +89,15 @@ void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr,
(I)[ISIS_SYS_ID_LEN] = 0; \
(I)[ISIS_SYS_ID_LEN + 1] = 0
int lsp_id_cmp(u_char *id1, u_char *id2);
int lsp_compare(char *areatag, struct isis_lsp *lsp, u_int32_t seq_num,
u_int16_t checksum, u_int16_t rem_lifetime);
void lsp_update(struct isis_lsp *lsp, struct stream *stream,
struct isis_area *area, int level);
void lsp_inc_seqnum(struct isis_lsp *lsp, u_int32_t seq_num);
int lsp_compare(char *areatag, struct isis_lsp *lsp, uint32_t seqno,
uint16_t checksum, uint16_t rem_lifetime);
void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
struct isis_tlvs *tlvs, struct stream *stream,
struct isis_area *area, int level, bool confusion);
void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno);
void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost);
void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost);
int lsp_print_all(struct vty *vty, dict_t *lspdb, char detail, char dynhost);
const char *lsp_bits2string(u_char *);
/* sets SRMflags for all active circuits of an lsp */
void lsp_set_all_srmflags(struct isis_lsp *lsp);

View File

@ -52,7 +52,6 @@
#include "isisd/isis_route.h"
#include "isisd/isis_routemap.h"
#include "isisd/isis_zebra.h"
#include "isisd/isis_tlv.h"
#include "isisd/isis_te.h"
/* Default configuration file name */

View File

@ -31,9 +31,9 @@ DEFINE_MTYPE(ISISD, ISIS_TMP, "ISIS TMP")
DEFINE_MTYPE(ISISD, ISIS_CIRCUIT, "ISIS circuit")
DEFINE_MTYPE(ISISD, ISIS_LSP, "ISIS LSP")
DEFINE_MTYPE(ISISD, ISIS_ADJACENCY, "ISIS adjacency")
DEFINE_MTYPE(ISISD, ISIS_ADJACENCY_INFO, "ISIS adjacency info")
DEFINE_MTYPE(ISISD, ISIS_AREA, "ISIS area")
DEFINE_MTYPE(ISISD, ISIS_AREA_ADDR, "ISIS area address")
DEFINE_MTYPE(ISISD, ISIS_TLV, "ISIS TLV")
DEFINE_MTYPE(ISISD, ISIS_DYNHN, "ISIS dyn hostname")
DEFINE_MTYPE(ISISD, ISIS_SPFTREE, "ISIS SPFtree")
DEFINE_MTYPE(ISISD, ISIS_VERTEX, "ISIS vertex")

View File

@ -30,9 +30,9 @@ DECLARE_MTYPE(ISIS_TMP)
DECLARE_MTYPE(ISIS_CIRCUIT)
DECLARE_MTYPE(ISIS_LSP)
DECLARE_MTYPE(ISIS_ADJACENCY)
DECLARE_MTYPE(ISIS_ADJACENCY_INFO)
DECLARE_MTYPE(ISIS_AREA)
DECLARE_MTYPE(ISIS_AREA_ADDR)
DECLARE_MTYPE(ISIS_TLV)
DECLARE_MTYPE(ISIS_DYNHN)
DECLARE_MTYPE(ISIS_SPFTREE)
DECLARE_MTYPE(ISIS_VERTEX)

View File

@ -28,6 +28,7 @@
#include "hash.h"
#include "if.h"
#include "command.h"
#include "log_int.h"
#include "isisd/dict.h"
#include "isisd/isis_constants.h"
@ -38,7 +39,6 @@
#include "isisd/isisd.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_adjacency.h"
@ -46,15 +46,9 @@
/* staticly assigned vars for printing purposes */
struct in_addr new_prefix;
/* len of xxxx.xxxx.xxxx + place for #0 termination */
char sysid[15];
/* len of xxxx.xxxx.xxxx + place for #0 termination */
char snpa[15];
/* len of xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx */
char isonet[51];
/* + place for #0 termination */
/* len of xxxx.xxxx.xxxx.xx.xx + place for #0 termination */
char lspid[21];
char isonet[51];
/* len of xxYxxMxWxdxxhxxmxxs + place for #0 termination */
char datestring[20];
char nlpidstring[30];
@ -179,6 +173,26 @@ int sysid2buff(u_char *buff, const char *dotted)
return len;
}
const char *nlpid2str(uint8_t nlpid)
{
static char buf[4];
switch (nlpid) {
case NLPID_IP:
return "IPv4";
case NLPID_IPV6:
return "IPv6";
case NLPID_SNAP:
return "SNAP";
case NLPID_CLNP:
return "CLNP";
case NLPID_ESIS:
return "ES-IS";
default:
snprintf(buf, sizeof(buf), "%" PRIu8, nlpid);
return buf;
}
}
/*
* converts the nlpids struct (filled by TLV #129)
* into a string
@ -190,26 +204,7 @@ char *nlpid2string(struct nlpids *nlpids)
int i;
for (i = 0; i < nlpids->count; i++) {
switch (nlpids->nlpids[i]) {
case NLPID_IP:
pos += sprintf(pos, "IPv4");
break;
case NLPID_IPV6:
pos += sprintf(pos, "IPv6");
break;
case NLPID_SNAP:
pos += sprintf(pos, "SNAP");
break;
case NLPID_CLNP:
pos += sprintf(pos, "CLNP");
break;
case NLPID_ESIS:
pos += sprintf(pos, "ES-IS");
break;
default:
pos += sprintf(pos, "unknown");
break;
}
pos += sprintf(pos, "%s", nlpid2str(nlpids->nlpids[i]));
if (nlpids->count - i > 1)
pos += sprintf(pos, ", ");
}
@ -219,25 +214,6 @@ char *nlpid2string(struct nlpids *nlpids)
return nlpidstring;
}
/*
* supports the given af ?
*/
int speaks(struct nlpids *nlpids, int family)
{
int i, speaks = 0;
if (nlpids == (struct nlpids *)NULL)
return speaks;
for (i = 0; i < nlpids->count; i++) {
if (family == AF_INET && nlpids->nlpids[i] == NLPID_IP)
speaks = 1;
if (family == AF_INET6 && nlpids->nlpids[i] == NLPID_IPV6)
speaks = 1;
}
return speaks;
}
/*
* Returns 0 on error, IS-IS Circuit Type on ok
*/
@ -330,71 +306,53 @@ const char *syst2string(int type)
*/
const char *snpa_print(const u_char *from)
{
int i = 0;
u_char *pos = (u_char *)snpa;
if (!from)
return "unknown";
while (i < ETH_ALEN - 1) {
if (i & 1) {
sprintf((char *)pos, "%02x.", *(from + i));
pos += 3;
} else {
sprintf((char *)pos, "%02x", *(from + i));
pos += 2;
}
i++;
}
sprintf((char *)pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
pos += 2;
*(pos) = '\0';
return snpa;
return isis_format_id(from, ISIS_SYS_ID_LEN);
}
const char *sysid_print(const u_char *from)
{
int i = 0;
char *pos = sysid;
if (!from)
return "unknown";
while (i < ISIS_SYS_ID_LEN - 1) {
if (i & 1) {
sprintf(pos, "%02x.", *(from + i));
pos += 3;
} else {
sprintf(pos, "%02x", *(from + i));
pos += 2;
}
i++;
}
sprintf(pos, "%02x", *(from + (ISIS_SYS_ID_LEN - 1)));
pos += 2;
*(pos) = '\0';
return sysid;
return isis_format_id(from, ISIS_SYS_ID_LEN);
}
const char *rawlspid_print(const u_char *from)
{
char *pos = lspid;
if (!from)
return "unknown";
memcpy(pos, sysid_print(from), 15);
pos += 14;
sprintf(pos, ".%02x", LSP_PSEUDO_ID(from));
pos += 3;
sprintf(pos, "-%02x", LSP_FRAGMENT(from));
pos += 3;
return isis_format_id(from, 8);
}
*(pos) = '\0';
#define FORMAT_ID_SIZE sizeof("0000.0000.0000.00-00")
const char *isis_format_id(const uint8_t *id, size_t len)
{
#define FORMAT_BUF_COUNT 4
static char buf_ring[FORMAT_BUF_COUNT][FORMAT_ID_SIZE];
static size_t cur_buf = 0;
return lspid;
char *rv;
cur_buf++;
if (cur_buf >= FORMAT_BUF_COUNT)
cur_buf = 0;
rv = buf_ring[cur_buf];
if (!id) {
snprintf(rv, FORMAT_ID_SIZE, "unknown");
return rv;
}
if (len < 6) {
snprintf(rv, FORMAT_ID_SIZE, "Short ID");
return rv;
}
snprintf(rv, FORMAT_ID_SIZE, "%02x%02x.%02x%02x.%02x%02x", id[0], id[1],
id[2], id[3], id[4], id[5]);
if (len > 6)
snprintf(rv + 14, FORMAT_ID_SIZE - 14, ".%02x", id[6]);
if (len > 7)
snprintf(rv + 17, FORMAT_ID_SIZE - 17, "-%02x", id[7]);
return rv;
}
const char *time2string(u_int32_t time)
@ -508,7 +466,7 @@ const char *print_sys_hostname(const u_char *sysid)
dyn = dynhn_find_by_id(sysid);
if (dyn)
return (const char *)dyn->name.name;
return dyn->hostname;
return sysid_print(sysid);
}
@ -572,3 +530,74 @@ void zlog_dump_data(void *data, int len)
zlog_debug("[%8.8s] %-50.50s %s", addrstr, hexstr, charstr);
return;
}
static char *qasprintf(const char *format, va_list ap)
{
va_list aq;
va_copy(aq, ap);
int size = 0;
char *p = NULL;
size = vsnprintf(p, size, format, ap);
if (size < 0) {
va_end(aq);
return NULL;
}
size++;
p = XMALLOC(MTYPE_TMP, size);
size = vsnprintf(p, size, format, aq);
va_end(aq);
if (size < 0) {
XFREE(MTYPE_TMP, p);
return NULL;
}
return p;
}
void log_multiline(int priority, const char *prefix, const char *format, ...)
{
va_list ap;
char *p;
va_start(ap, format);
p = qasprintf(format, ap);
va_end(ap);
if (!p)
return;
char *saveptr = NULL;
for (char *line = strtok_r(p, "\n", &saveptr); line;
line = strtok_r(NULL, "\n", &saveptr)) {
zlog(priority, "%s%s", prefix, line);
}
XFREE(MTYPE_TMP, p);
}
void vty_multiline(struct vty *vty, const char *prefix, const char *format, ...)
{
va_list ap;
char *p;
va_start(ap, format);
p = qasprintf(format, ap);
va_end(ap);
if (!p)
return;
char *saveptr = NULL;
for (char *line = strtok_r(p, "\n", &saveptr); line;
line = strtok_r(NULL, "\n", &saveptr)) {
vty_out(vty, "%s%s\n", prefix, line);
}
XFREE(MTYPE_TMP, p);
}

View File

@ -44,7 +44,9 @@ const char *isonet_print(const u_char *, int len);
const char *sysid_print(const u_char *);
const char *snpa_print(const u_char *);
const char *rawlspid_print(const u_char *);
const char *isis_format_id(const uint8_t *id, size_t len);
const char *time2string(u_int32_t);
const char *nlpid2str(uint8_t nlpid);
/* typedef struct nlpids nlpids; */
char *nlpid2string(struct nlpids *);
const char *print_sys_hostname(const u_char *sysid);
@ -53,7 +55,6 @@ void zlog_dump_data(void *data, int len);
/*
* misc functions
*/
int speaks(struct nlpids *nlpids, int family);
unsigned long isis_jitter(unsigned long timer, unsigned long jitter);
const char *unix_hostname(void);
@ -77,4 +78,10 @@ enum { ISIS_UI_LEVEL_BRIEF,
ISIS_UI_LEVEL_EXTENSIVE,
};
#include "lib/log.h"
void log_multiline(int priority, const char *prefix, const char *format, ...)
PRINTF_ATTRIBUTE(3, 4);
struct vty;
void vty_multiline(struct vty *vty, const char *prefix, const char *format, ...)
PRINTF_ATTRIBUTE(3, 4);
#endif

View File

@ -24,19 +24,14 @@
#include "isisd/isis_memory.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_adjacency.h"
#include "isisd/isis_tlv.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_mt.h"
#include "isisd/isis_tlvs.h"
DEFINE_MTYPE_STATIC(ISISD, MT_AREA_SETTING, "ISIS MT Area Setting")
DEFINE_MTYPE_STATIC(ISISD, MT_CIRCUIT_SETTING, "ISIS MT Circuit Setting")
DEFINE_MTYPE_STATIC(ISISD, MT_ADJ_INFO, "ISIS MT Adjacency Info")
DEFINE_MTYPE_STATIC(ISISD, MT_NEIGHBORS, "ISIS MT Neighbors for TLV")
DEFINE_MTYPE_STATIC(ISISD, MT_IPV4_REACHS,
"ISIS MT IPv4 Reachabilities for TLV")
DEFINE_MTYPE_STATIC(ISISD, MT_IPV6_REACHS,
"ISIS MT IPv6 Reachabilities for TLV")
uint16_t isis_area_ipv6_topology(struct isis_area *area)
{
@ -367,7 +362,7 @@ static void adj_mt_set(struct isis_adjacency *adj, unsigned int index,
adj->mt_set[index] = mtid;
}
bool tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable,
bool tlvs_to_adj_mt_set(struct isis_tlvs *tlvs, bool v4_usable, bool v6_usable,
struct isis_adjacency *adj)
{
struct isis_circuit_mt_setting **mt_settings;
@ -388,17 +383,20 @@ bool tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable,
mt_settings = circuit_mt_settings(adj->circuit, &circuit_mt_count);
for (unsigned int i = 0; i < circuit_mt_count; i++) {
if (!tlvs->mt_router_info) {
if (!tlvs->mt_router_info.count
&& !tlvs->mt_router_info_empty) {
/* Other end does not have MT enabled */
if (mt_settings[i]->mtid == ISIS_MT_IPV4_UNICAST
&& v4_usable)
adj_mt_set(adj, intersect_count++,
ISIS_MT_IPV4_UNICAST);
} else {
struct listnode *node;
struct mt_router_info *info;
for (ALL_LIST_ELEMENTS_RO(tlvs->mt_router_info, node,
info)) {
struct isis_mt_router_info *info_head;
info_head = (struct isis_mt_router_info *)
tlvs->mt_router_info.head;
for (struct isis_mt_router_info *info = info_head; info;
info = info->next) {
if (mt_settings[i]->mtid == info->mtid) {
bool usable;
switch (info->mtid) {
@ -456,153 +454,6 @@ void adj_mt_finish(struct isis_adjacency *adj)
adj->mt_count = 0;
}
/* TLV Router info api */
struct mt_router_info *tlvs_lookup_mt_router_info(struct tlvs *tlvs,
uint16_t mtid)
{
return lookup_mt_setting(tlvs->mt_router_info, mtid);
}
/* TLV MT Neighbors api */
struct tlv_mt_neighbors *tlvs_lookup_mt_neighbors(struct tlvs *tlvs,
uint16_t mtid)
{
return lookup_mt_setting(tlvs->mt_is_neighs, mtid);
}
static struct tlv_mt_neighbors *tlvs_new_mt_neighbors(uint16_t mtid)
{
struct tlv_mt_neighbors *rv;
rv = XCALLOC(MTYPE_MT_NEIGHBORS, sizeof(*rv));
rv->mtid = mtid;
rv->list = list_new();
return rv;
};
static void tlvs_free_mt_neighbors(void *arg)
{
struct tlv_mt_neighbors *neighbors = arg;
if (neighbors && neighbors->list)
list_delete(neighbors->list);
XFREE(MTYPE_MT_NEIGHBORS, neighbors);
}
static void tlvs_add_mt_neighbors(struct tlvs *tlvs,
struct tlv_mt_neighbors *neighbors)
{
add_mt_setting(&tlvs->mt_is_neighs, neighbors);
tlvs->mt_is_neighs->del = tlvs_free_mt_neighbors;
}
struct tlv_mt_neighbors *tlvs_get_mt_neighbors(struct tlvs *tlvs, uint16_t mtid)
{
struct tlv_mt_neighbors *neighbors;
neighbors = tlvs_lookup_mt_neighbors(tlvs, mtid);
if (!neighbors) {
neighbors = tlvs_new_mt_neighbors(mtid);
tlvs_add_mt_neighbors(tlvs, neighbors);
}
return neighbors;
}
/* TLV MT IPv4 reach api */
struct tlv_mt_ipv4_reachs *tlvs_lookup_mt_ipv4_reachs(struct tlvs *tlvs,
uint16_t mtid)
{
return lookup_mt_setting(tlvs->mt_ipv4_reachs, mtid);
}
static struct tlv_mt_ipv4_reachs *tlvs_new_mt_ipv4_reachs(uint16_t mtid)
{
struct tlv_mt_ipv4_reachs *rv;
rv = XCALLOC(MTYPE_MT_IPV4_REACHS, sizeof(*rv));
rv->mtid = mtid;
rv->list = list_new();
return rv;
};
static void tlvs_free_mt_ipv4_reachs(void *arg)
{
struct tlv_mt_ipv4_reachs *reachs = arg;
if (reachs && reachs->list)
list_delete(reachs->list);
XFREE(MTYPE_MT_IPV4_REACHS, reachs);
}
static void tlvs_add_mt_ipv4_reachs(struct tlvs *tlvs,
struct tlv_mt_ipv4_reachs *reachs)
{
add_mt_setting(&tlvs->mt_ipv4_reachs, reachs);
tlvs->mt_ipv4_reachs->del = tlvs_free_mt_ipv4_reachs;
}
struct tlv_mt_ipv4_reachs *tlvs_get_mt_ipv4_reachs(struct tlvs *tlvs,
uint16_t mtid)
{
struct tlv_mt_ipv4_reachs *reachs;
reachs = tlvs_lookup_mt_ipv4_reachs(tlvs, mtid);
if (!reachs) {
reachs = tlvs_new_mt_ipv4_reachs(mtid);
tlvs_add_mt_ipv4_reachs(tlvs, reachs);
}
return reachs;
}
/* TLV MT IPv6 reach api */
struct tlv_mt_ipv6_reachs *tlvs_lookup_mt_ipv6_reachs(struct tlvs *tlvs,
uint16_t mtid)
{
return lookup_mt_setting(tlvs->mt_ipv6_reachs, mtid);
}
static struct tlv_mt_ipv6_reachs *tlvs_new_mt_ipv6_reachs(uint16_t mtid)
{
struct tlv_mt_ipv6_reachs *rv;
rv = XCALLOC(MTYPE_MT_IPV6_REACHS, sizeof(*rv));
rv->mtid = mtid;
rv->list = list_new();
return rv;
};
static void tlvs_free_mt_ipv6_reachs(void *arg)
{
struct tlv_mt_ipv6_reachs *reachs = arg;
if (reachs && reachs->list)
list_delete(reachs->list);
XFREE(MTYPE_MT_IPV6_REACHS, reachs);
}
static void tlvs_add_mt_ipv6_reachs(struct tlvs *tlvs,
struct tlv_mt_ipv6_reachs *reachs)
{
add_mt_setting(&tlvs->mt_ipv6_reachs, reachs);
tlvs->mt_ipv6_reachs->del = tlvs_free_mt_ipv6_reachs;
}
struct tlv_mt_ipv6_reachs *tlvs_get_mt_ipv6_reachs(struct tlvs *tlvs,
uint16_t mtid)
{
struct tlv_mt_ipv6_reachs *reachs;
reachs = tlvs_lookup_mt_ipv6_reachs(tlvs, mtid);
if (!reachs) {
reachs = tlvs_new_mt_ipv6_reachs(mtid);
tlvs_add_mt_ipv6_reachs(tlvs, reachs);
}
return reachs;
}
static void mt_set_add(uint16_t **mt_set, unsigned int *size,
unsigned int *index, uint16_t mtid)
{
@ -647,51 +498,46 @@ static uint16_t *circuit_bcast_mt_set(struct isis_circuit *circuit, int level,
return rv;
}
static void tlvs_add_mt_set(struct isis_area *area, struct tlvs *tlvs,
static void tlvs_add_mt_set(struct isis_area *area, struct isis_tlvs *tlvs,
unsigned int mt_count, uint16_t *mt_set,
struct te_is_neigh *neigh)
uint8_t *id, uint32_t metric, uint8_t *subtlvs,
uint8_t subtlv_len)
{
for (unsigned int i = 0; i < mt_count; i++) {
uint16_t mtid = mt_set[i];
struct te_is_neigh *ne_copy;
ne_copy = XCALLOC(MTYPE_ISIS_TLV, sizeof(*ne_copy));
memcpy(ne_copy, neigh, sizeof(*ne_copy));
if (mt_set[i] == ISIS_MT_IPV4_UNICAST) {
listnode_add(tlvs->te_is_neighs, ne_copy);
lsp_debug(
"ISIS (%s): Adding %s.%02x as te-style neighbor",
area->area_tag, sysid_print(ne_copy->neigh_id),
LSP_PSEUDO_ID(ne_copy->neigh_id));
area->area_tag, sysid_print(id),
LSP_PSEUDO_ID(id));
} else {
struct tlv_mt_neighbors *neighbors;
neighbors = tlvs_get_mt_neighbors(tlvs, mtid);
neighbors->list->del = free_tlv;
listnode_add(neighbors->list, ne_copy);
lsp_debug(
"ISIS (%s): Adding %s.%02x as mt-style neighbor for %s",
area->area_tag, sysid_print(ne_copy->neigh_id),
LSP_PSEUDO_ID(ne_copy->neigh_id),
isis_mtid2str(mtid));
area->area_tag, sysid_print(id),
LSP_PSEUDO_ID(id), isis_mtid2str(mtid));
}
isis_tlvs_add_extended_reach(tlvs, mtid, id, metric, subtlvs,
subtlv_len);
}
}
void tlvs_add_mt_bcast(struct tlvs *tlvs, struct isis_circuit *circuit,
int level, struct te_is_neigh *neigh)
void tlvs_add_mt_bcast(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
int level, uint8_t *id, uint32_t metric,
uint8_t *subtlvs, uint8_t subtlv_len)
{
unsigned int mt_count;
uint16_t *mt_set = circuit_bcast_mt_set(circuit, level, &mt_count);
tlvs_add_mt_set(circuit->area, tlvs, mt_count, mt_set, neigh);
tlvs_add_mt_set(circuit->area, tlvs, mt_count, mt_set, id, metric,
subtlvs, subtlv_len);
}
void tlvs_add_mt_p2p(struct tlvs *tlvs, struct isis_circuit *circuit,
struct te_is_neigh *neigh)
void tlvs_add_mt_p2p(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
uint8_t *id, uint32_t metric, uint8_t *subtlvs,
uint8_t subtlv_len)
{
struct isis_adjacency *adj = circuit->u.p2p.neighbor;
tlvs_add_mt_set(circuit->area, tlvs, adj->mt_count, adj->mt_set, neigh);
tlvs_add_mt_set(circuit->area, tlvs, adj->mt_count, adj->mt_set, id,
metric, subtlvs, subtlv_len);
}

View File

@ -24,6 +24,7 @@
#define ISIS_MT_MASK 0x0fff
#define ISIS_MT_OL_MASK 0x8000
#define ISIS_MT_AT_MASK 0x4000
#define ISIS_MT_IPV4_UNICAST 0
#define ISIS_MT_IPV4_MGMT 1
@ -64,21 +65,6 @@ struct isis_circuit_mt_setting {
bool enabled;
};
struct tlv_mt_neighbors {
ISIS_MT_INFO_FIELDS
struct list *list;
};
struct tlv_mt_ipv4_reachs {
ISIS_MT_INFO_FIELDS
struct list *list;
};
struct tlv_mt_ipv6_reachs {
ISIS_MT_INFO_FIELDS
struct list *list;
};
const char *isis_mtid2str(uint16_t mtid);
uint16_t isis_str2mtid(const char *name);
@ -87,27 +73,10 @@ struct isis_area;
struct isis_circuit;
struct tlvs;
struct te_is_neigh;
struct isis_tlvs;
uint16_t isis_area_ipv6_topology(struct isis_area *area);
struct mt_router_info *tlvs_lookup_mt_router_info(struct tlvs *tlvs,
uint16_t mtid);
struct tlv_mt_neighbors *tlvs_lookup_mt_neighbors(struct tlvs *tlvs,
uint16_t mtid);
struct tlv_mt_neighbors *tlvs_get_mt_neighbors(struct tlvs *tlvs,
uint16_t mtid);
struct tlv_mt_ipv4_reachs *tlvs_lookup_mt_ipv4_reachs(struct tlvs *tlvs,
uint16_t mtid);
struct tlv_mt_ipv4_reachs *tlvs_get_mt_ipv4_reachs(struct tlvs *tlvs,
uint16_t mtid);
struct tlv_mt_ipv6_reachs *tlvs_lookup_mt_ipv6_reachs(struct tlvs *tlvs,
uint16_t mtid);
struct tlv_mt_ipv6_reachs *tlvs_get_mt_ipv6_reachs(struct tlvs *tlvs,
uint16_t mtid);
struct isis_area_mt_setting *area_lookup_mt_setting(struct isis_area *area,
uint16_t mtid);
struct isis_area_mt_setting *area_new_mt_setting(struct isis_area *area,
@ -137,12 +106,14 @@ circuit_get_mt_setting(struct isis_circuit *circuit, uint16_t mtid);
int circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty);
struct isis_circuit_mt_setting **
circuit_mt_settings(struct isis_circuit *circuit, unsigned int *mt_count);
bool tlvs_to_adj_mt_set(struct tlvs *tlvs, bool v4_usable, bool v6_usable,
bool tlvs_to_adj_mt_set(struct isis_tlvs *tlvs, bool v4_usable, bool v6_usable,
struct isis_adjacency *adj);
bool adj_has_mt(struct isis_adjacency *adj, uint16_t mtid);
void adj_mt_finish(struct isis_adjacency *adj);
void tlvs_add_mt_bcast(struct tlvs *tlvs, struct isis_circuit *circuit,
int level, struct te_is_neigh *neigh);
void tlvs_add_mt_p2p(struct tlvs *tlvs, struct isis_circuit *circuit,
struct te_is_neigh *neigh);
void tlvs_add_mt_bcast(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
int level, uint8_t *id, uint32_t metric,
uint8_t *subtlvs, uint8_t subtlv_len);
void tlvs_add_mt_p2p(struct isis_tlvs *tlvs, struct isis_circuit *circuit,
uint8_t *id, uint32_t metric, uint8_t *subtlvs,
uint8_t subtlv_len);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -65,36 +65,6 @@ struct esis_fixed_hdr {
#define ISH_PDU 4
#define RD_PDU 5
/*
* IS to IS Fixed Header
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | Intradomain Routeing Protocol Discriminator |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | Length Indicator |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | Version/Protocol ID extension |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | R | R | R | PDU Type |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | Version |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | Reserved |
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | Maximum Area Addresses |
* +-------+-------+-------+-------+-------+-------+-------+-------+
*/
struct isis_fixed_hdr {
u_char idrp;
u_char length;
u_char version1;
u_char id_len;
u_char pdu_type;
u_char version2;
u_char reserved;
u_char max_area_addrs;
} __attribute__((packed));
#define ISIS_FIXED_HDR_LEN 8
/*
@ -155,30 +125,14 @@ struct isis_p2p_hello_hdr {
#define L1_LINK_STATE 18
#define L2_LINK_STATE 20
/*
* L1 and L2 IS to IS link state PDU header
* +-------+-------+-------+-------+-------+-------+-------+-------+
* + PDU Length + 2
* +-------+-------+-------+-------+-------+-------+-------+-------+
* + Remaining Lifetime + 2
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | LSP ID | id_len + 2
* +-------+-------+-------+-------+-------+-------+-------+-------+
* + Sequence Number + 4
* +-------+-------+-------+-------+-------+-------+-------+-------+
* + Checksum + 2
* +-------+-------+-------+-------+-------+-------+-------+-------+
* | P | ATT |LSPDBOL| ISTYPE |
* +-------+-------+-------+-------+-------+-------+-------+-------+
*/
struct isis_link_state_hdr {
u_int16_t pdu_len;
u_int16_t rem_lifetime;
u_char lsp_id[ISIS_SYS_ID_LEN + 2];
u_int32_t seq_num;
u_int16_t checksum;
u_int8_t lsp_bits;
} __attribute__((packed));
struct isis_lsp_hdr {
uint16_t pdu_len;
uint16_t rem_lifetime;
uint8_t lsp_id[ISIS_SYS_ID_LEN + 2];
uint32_t seqno;
uint16_t checksum;
uint8_t lsp_bits;
};
#define ISIS_LSP_HDR_LEN 19
/*
@ -259,9 +213,7 @@ int send_l2_csnp(struct thread *thread);
int send_l1_psnp(struct thread *thread);
int send_l2_psnp(struct thread *thread);
int send_lsp(struct thread *thread);
int ack_lsp(struct isis_link_state_hdr *hdr, struct isis_circuit *circuit,
int level);
void fill_fixed_hdr(struct isis_fixed_hdr *hdr, u_char pdu_type);
void fill_fixed_hdr(uint8_t pdu_type, struct stream *stream);
int send_hello(struct isis_circuit *circuit, int level);
#endif /* _ZEBRA_ISIS_PDU_H */

View File

@ -37,7 +37,6 @@
#include "isisd/isis_flags.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_tlv.h"
#include "isisd/isisd.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_route.h"

View File

@ -42,7 +42,6 @@
#include "isis_misc.h"
#include "isis_adjacency.h"
#include "isis_circuit.h"
#include "isis_tlv.h"
#include "isis_pdu.h"
#include "isis_lsp.h"
#include "isis_spf.h"
@ -208,13 +207,12 @@ static void nexthops6_print(struct list *nhs6)
static void adjinfo2nexthop(struct list *nexthops, struct isis_adjacency *adj)
{
struct isis_nexthop *nh;
struct listnode *node;
struct in_addr *ipv4_addr;
if (adj->ipv4_addrs == NULL)
if (!adj->ipv4_address_count)
return;
for (ALL_LIST_ELEMENTS_RO(adj->ipv4_addrs, node, ipv4_addr)) {
for (unsigned int i = 0; i < adj->ipv4_address_count; i++) {
struct in_addr *ipv4_addr = &adj->ipv4_addresses[i];
if (!nexthoplookup(nexthops, ipv4_addr,
adj->circuit->interface->ifindex)) {
nh = isis_nexthop_create(
@ -227,14 +225,13 @@ static void adjinfo2nexthop(struct list *nexthops, struct isis_adjacency *adj)
static void adjinfo2nexthop6(struct list *nexthops6, struct isis_adjacency *adj)
{
struct listnode *node;
struct in6_addr *ipv6_addr;
struct isis_nexthop6 *nh6;
if (!adj->ipv6_addrs)
if (!adj->ipv6_address_count)
return;
for (ALL_LIST_ELEMENTS_RO(adj->ipv6_addrs, node, ipv6_addr)) {
for (unsigned int i = 0; i < adj->ipv6_address_count; i++) {
struct in6_addr *ipv6_addr = &adj->ipv6_addresses[i];
if (!nexthop6lookup(nexthops6, ipv6_addr,
adj->circuit->interface->ifindex)) {
nh6 = isis_nexthop6_create(

View File

@ -42,7 +42,6 @@
#include "isis_misc.h"
#include "isis_adjacency.h"
#include "isis_circuit.h"
#include "isis_tlv.h"
#include "isis_pdu.h"
#include "isis_lsp.h"
#include "isis_spf.h"

View File

@ -44,7 +44,6 @@
#include "isis_misc.h"
#include "isis_adjacency.h"
#include "isis_circuit.h"
#include "isis_tlv.h"
#include "isis_pdu.h"
#include "isis_lsp.h"
#include "isis_dynhn.h"
@ -52,9 +51,24 @@
#include "isis_route.h"
#include "isis_csm.h"
#include "isis_mt.h"
#include "isis_tlvs.h"
DEFINE_MTYPE_STATIC(ISISD, ISIS_SPF_RUN, "ISIS SPF Run Info");
/*
* supports the given af ?
*/
static bool speaks(uint8_t *protocols, uint8_t count, int family)
{
for (uint8_t i = 0; i < count; i++) {
if (family == AF_INET && protocols[i] == NLPID_IP)
return true;
if (family == AF_INET6 && protocols[i] == NLPID_IPV6)
return true;
}
return false;
}
struct isis_spf_run {
struct isis_area *area;
int level;
@ -340,7 +354,7 @@ static struct isis_lsp *isis_root_system_lsp(struct isis_area *area, int level,
LSP_PSEUDO_ID(lspid) = 0;
LSP_FRAGMENT(lspid) = 0;
lsp = lsp_search(lspid, area->lspdb[level - 1]);
if (lsp && lsp->lsp_header->rem_lifetime != 0)
if (lsp && lsp->hdr.rem_lifetime != 0)
return lsp;
return NULL;
}
@ -546,6 +560,13 @@ static void process_N(struct isis_spftree *spftree, enum vertextype vtype,
assert(spftree && parent);
struct prefix p;
if (vtype >= VTYPE_IPREACH_INTERNAL) {
prefix_copy(&p, id);
apply_mask(&p);
id = &p;
}
/* RFC3787 section 5.1 */
if (spftree->area->newmetric == 1) {
if (dist > MAX_WIDE_PATH_METRIC)
@ -632,30 +653,35 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree,
uint16_t depth, u_char *root_sysid,
struct isis_vertex *parent)
{
bool pseudo_lsp = LSP_PSEUDO_ID(lsp->lsp_header->lsp_id);
struct listnode *node, *fragnode = NULL;
bool pseudo_lsp = LSP_PSEUDO_ID(lsp->hdr.lsp_id);
struct listnode *fragnode = NULL;
uint32_t dist;
struct is_neigh *is_neigh;
struct te_is_neigh *te_is_neigh;
struct ipv4_reachability *ipreach;
struct te_ipv4_reachability *te_ipv4_reach;
enum vertextype vtype;
struct prefix prefix;
struct ipv6_reachability *ip6reach;
static const u_char null_sysid[ISIS_SYS_ID_LEN];
struct mt_router_info *mt_router_info = NULL;
struct isis_mt_router_info *mt_router_info = NULL;
if (!lsp->tlvs)
return ISIS_OK;
if (spftree->mtid != ISIS_MT_IPV4_UNICAST)
mt_router_info = tlvs_lookup_mt_router_info(&lsp->tlv_data,
spftree->mtid);
mt_router_info = isis_tlvs_lookup_mt_router_info(lsp->tlvs,
spftree->mtid);
if (!pseudo_lsp && (spftree->mtid == ISIS_MT_IPV4_UNICAST
&& !speaks(lsp->tlv_data.nlpids, spftree->family))
&& !speaks(lsp->tlvs->protocols_supported.protocols,
lsp->tlvs->protocols_supported.count,
spftree->family))
&& !mt_router_info)
return ISIS_OK;
/* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */
bool no_overload = (pseudo_lsp
|| (spftree->mtid == ISIS_MT_IPV4_UNICAST
&& !ISIS_MASK_LSP_OL_BIT(lsp->hdr.lsp_bits))
|| (mt_router_info && !mt_router_info->overload));
lspfragloop:
if (lsp->lsp_header->seq_num == 0) {
if (lsp->hdr.seqno == 0) {
zlog_warn(
"isis_spf_process_lsp(): lsp with 0 seq_num - ignore");
return ISIS_WARNING;
@ -663,142 +689,117 @@ lspfragloop:
#ifdef EXTREME_DEBUG
zlog_debug("ISIS-Spf: process_lsp %s",
print_sys_hostname(lsp->lsp_header->lsp_id));
print_sys_hostname(lsp->hdr.lsp_id));
#endif /* EXTREME_DEBUG */
/* RFC3787 section 4 SHOULD ignore overload bit in pseudo LSPs */
if (pseudo_lsp || (spftree->mtid == ISIS_MT_IPV4_UNICAST
&& !ISIS_MASK_LSP_OL_BIT(lsp->lsp_header->lsp_bits))
|| (mt_router_info && !mt_router_info->overload))
{
if (no_overload) {
if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) {
for (ALL_LIST_ELEMENTS_RO(lsp->tlv_data.is_neighs, node,
is_neigh)) {
struct isis_oldstyle_reach *r;
for (r = (struct isis_oldstyle_reach *)
lsp->tlvs->oldstyle_reach.head;
r; r = r->next) {
/* C.2.6 a) */
/* Two way connectivity */
if (!memcmp(is_neigh->neigh_id, root_sysid,
ISIS_SYS_ID_LEN))
if (!memcmp(r->id, root_sysid, ISIS_SYS_ID_LEN))
continue;
if (!pseudo_lsp
&& !memcmp(is_neigh->neigh_id, null_sysid,
&& !memcmp(r->id, null_sysid,
ISIS_SYS_ID_LEN))
continue;
dist = cost + is_neigh->metrics.metric_default;
dist = cost + r->metric;
process_N(spftree,
LSP_PSEUDO_ID(is_neigh->neigh_id)
LSP_PSEUDO_ID(r->id)
? VTYPE_PSEUDO_IS
: VTYPE_NONPSEUDO_IS,
(void *)is_neigh->neigh_id, dist,
depth + 1, parent);
(void *)r->id, dist, depth + 1,
parent);
}
}
struct list *te_is_neighs = NULL;
if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST) {
te_is_neighs = lsp->tlv_data.te_is_neighs;
} else {
struct tlv_mt_neighbors *mt_neighbors;
mt_neighbors = tlvs_lookup_mt_neighbors(&lsp->tlv_data,
spftree->mtid);
if (mt_neighbors)
te_is_neighs = mt_neighbors->list;
}
for (ALL_LIST_ELEMENTS_RO(te_is_neighs, node, te_is_neigh)) {
if (!memcmp(te_is_neigh->neigh_id, root_sysid,
ISIS_SYS_ID_LEN))
struct isis_item_list *te_neighs = NULL;
if (pseudo_lsp || spftree->mtid == ISIS_MT_IPV4_UNICAST)
te_neighs = &lsp->tlvs->extended_reach;
else
te_neighs = isis_lookup_mt_items(&lsp->tlvs->mt_reach,
spftree->mtid);
struct isis_extended_reach *er;
for (er = te_neighs
? (struct isis_extended_reach *)
te_neighs->head
: NULL;
er; er = er->next) {
if (!memcmp(er->id, root_sysid, ISIS_SYS_ID_LEN))
continue;
if (!pseudo_lsp
&& !memcmp(te_is_neigh->neigh_id, null_sysid,
ISIS_SYS_ID_LEN))
&& !memcmp(er->id, null_sysid, ISIS_SYS_ID_LEN))
continue;
dist = cost + GET_TE_METRIC(te_is_neigh);
dist = cost + er->metric;
process_N(spftree,
LSP_PSEUDO_ID(te_is_neigh->neigh_id)
? VTYPE_PSEUDO_TE_IS
: VTYPE_NONPSEUDO_TE_IS,
(void *)te_is_neigh->neigh_id, dist,
depth + 1, parent);
LSP_PSEUDO_ID(er->id) ? VTYPE_PSEUDO_TE_IS
: VTYPE_NONPSEUDO_TE_IS,
(void *)er->id, dist, depth + 1, parent);
}
}
if (!pseudo_lsp && spftree->family == AF_INET
&& spftree->mtid == ISIS_MT_IPV4_UNICAST) {
struct list *reachs[] = {lsp->tlv_data.ipv4_int_reachs,
lsp->tlv_data.ipv4_ext_reachs};
struct isis_item_list *reachs[] = {
&lsp->tlvs->oldstyle_ip_reach,
&lsp->tlvs->oldstyle_ip_reach_ext};
prefix.family = AF_INET;
for (unsigned int i = 0; i < array_size(reachs); i++) {
vtype = (reachs[i] == lsp->tlv_data.ipv4_int_reachs)
? VTYPE_IPREACH_INTERNAL
: VTYPE_IPREACH_EXTERNAL;
for (ALL_LIST_ELEMENTS_RO(reachs[i], node, ipreach)) {
dist = cost + ipreach->metrics.metric_default;
prefix.u.prefix4 = ipreach->prefix;
prefix.prefixlen = ip_masklen(ipreach->mask);
apply_mask(&prefix);
process_N(spftree, vtype, (void *)&prefix, dist,
depth + 1, parent);
vtype = i ? VTYPE_IPREACH_EXTERNAL
: VTYPE_IPREACH_INTERNAL;
struct isis_oldstyle_ip_reach *r;
for (r = (struct isis_oldstyle_ip_reach *)reachs[i]
->head;
r; r = r->next) {
dist = cost + r->metric;
process_N(spftree, vtype, (void *)&r->prefix,
dist, depth + 1, parent);
}
}
}
if (!pseudo_lsp && spftree->family == AF_INET) {
struct list *ipv4reachs = NULL;
struct isis_item_list *ipv4_reachs;
if (spftree->mtid == ISIS_MT_IPV4_UNICAST)
ipv4_reachs = &lsp->tlvs->extended_ip_reach;
else
ipv4_reachs = isis_lookup_mt_items(
&lsp->tlvs->mt_ip_reach, spftree->mtid);
if (spftree->mtid == ISIS_MT_IPV4_UNICAST) {
ipv4reachs = lsp->tlv_data.te_ipv4_reachs;
} else {
struct tlv_mt_ipv4_reachs *mt_reachs;
mt_reachs = tlvs_lookup_mt_ipv4_reachs(&lsp->tlv_data,
spftree->mtid);
if (mt_reachs)
ipv4reachs = mt_reachs->list;
}
prefix.family = AF_INET;
for (ALL_LIST_ELEMENTS_RO(ipv4reachs, node, te_ipv4_reach)) {
assert((te_ipv4_reach->control & 0x3F)
<= IPV4_MAX_BITLEN);
dist = cost + ntohl(te_ipv4_reach->te_metric);
prefix.u.prefix4 =
newprefix2inaddr(&te_ipv4_reach->prefix_start,
te_ipv4_reach->control);
prefix.prefixlen = (te_ipv4_reach->control & 0x3F);
apply_mask(&prefix);
process_N(spftree, VTYPE_IPREACH_TE, (void *)&prefix,
struct isis_extended_ip_reach *r;
for (r = ipv4_reachs
? (struct isis_extended_ip_reach *)
ipv4_reachs->head
: NULL;
r; r = r->next) {
dist = cost + r->metric;
process_N(spftree, VTYPE_IPREACH_TE, (void *)&r->prefix,
dist, depth + 1, parent);
}
}
if (!pseudo_lsp && spftree->family == AF_INET6) {
struct list *ipv6reachs = NULL;
struct isis_item_list *ipv6_reachs;
if (spftree->mtid == ISIS_MT_IPV4_UNICAST)
ipv6_reachs = &lsp->tlvs->ipv6_reach;
else
ipv6_reachs = isis_lookup_mt_items(
&lsp->tlvs->mt_ipv6_reach, spftree->mtid);
if (spftree->mtid == ISIS_MT_IPV4_UNICAST) {
ipv6reachs = lsp->tlv_data.ipv6_reachs;
} else {
struct tlv_mt_ipv6_reachs *mt_reachs;
mt_reachs = tlvs_lookup_mt_ipv6_reachs(&lsp->tlv_data,
spftree->mtid);
if (mt_reachs)
ipv6reachs = mt_reachs->list;
}
prefix.family = AF_INET6;
for (ALL_LIST_ELEMENTS_RO(ipv6reachs, node, ip6reach)) {
assert(ip6reach->prefix_len <= IPV6_MAX_BITLEN);
dist = cost + ntohl(ip6reach->metric);
vtype = (ip6reach->control_info
& CTRL_INFO_DISTRIBUTION)
? VTYPE_IP6REACH_EXTERNAL
: VTYPE_IP6REACH_INTERNAL;
prefix.prefixlen = ip6reach->prefix_len;
memcpy(&prefix.u.prefix6.s6_addr, ip6reach->prefix,
PSIZE(ip6reach->prefix_len));
apply_mask(&prefix);
process_N(spftree, vtype, (void *)&prefix, dist,
struct isis_ipv6_reach *r;
for (r = ipv6_reachs
? (struct isis_ipv6_reach *)ipv6_reachs->head
: NULL;
r; r = r->next) {
dist = cost + r->metric;
vtype = r->external ? VTYPE_IP6REACH_EXTERNAL
: VTYPE_IP6REACH_INTERNAL;
process_N(spftree, vtype, (void *)&r->prefix, dist,
depth + 1, parent);
}
}
@ -893,7 +894,9 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
if (!adj_has_mt(adj, spftree->mtid))
continue;
if (spftree->mtid == ISIS_MT_IPV4_UNICAST
&& !speaks(&adj->nlpids, spftree->family))
&& !speaks(adj->nlpids.nlpids,
adj->nlpids.count,
spftree->family))
continue;
switch (adj->sys_type) {
case ISIS_SYSTYPE_ES:
@ -928,8 +931,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
->lspdb[spftree->level
- 1]);
if (lsp == NULL
|| lsp->lsp_header->rem_lifetime
== 0)
|| lsp->hdr.rem_lifetime == 0)
zlog_warn(
"ISIS-Spf: No LSP %s found for IS adjacency "
"L%d on %s (ID %u)",
@ -979,7 +981,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
lsp = lsp_search(
lsp_id,
spftree->area->lspdb[spftree->level - 1]);
if (lsp == NULL || lsp->lsp_header->rem_lifetime == 0) {
if (lsp == NULL || lsp->hdr.rem_lifetime == 0) {
zlog_warn(
"ISIS-Spf: No lsp (%p) found from root "
"to L%d DR %s on %s (ID %d)",
@ -1015,7 +1017,9 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree,
LSP_PSEUDO_ID(lsp_id) = 0;
LSP_FRAGMENT(lsp_id) = 0;
if (spftree->mtid != ISIS_MT_IPV4_UNICAST
|| speaks(&adj->nlpids, spftree->family))
|| speaks(adj->nlpids.nlpids,
adj->nlpids.count,
spftree->family))
isis_spf_add_local(
spftree,
spftree->area->oldmetric
@ -1178,7 +1182,7 @@ static int isis_run_spf(struct isis_area *area, int level, int family,
memcpy(lsp_id, vertex->N.id, ISIS_SYS_ID_LEN + 1);
LSP_FRAGMENT(lsp_id) = 0;
lsp = lsp_search(lsp_id, area->lspdb[level - 1]);
if (lsp && lsp->lsp_header->rem_lifetime != 0) {
if (lsp && lsp->hdr.rem_lifetime != 0) {
isis_spf_process_lsp(spftree, lsp, vertex->d_N,
vertex->depth, sysid,
vertex);

View File

@ -41,6 +41,7 @@
#include "md5.h"
#include "sockunion.h"
#include "network.h"
#include "sbuf.h"
#include "isisd/dict.h"
#include "isisd/isis_constants.h"
@ -48,7 +49,6 @@
#include "isisd/isis_flags.h"
#include "isisd/isis_circuit.h"
#include "isisd/isisd.h"
#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_pdu.h"
#include "isisd/isis_dynhn.h"
@ -100,9 +100,9 @@ struct mpls_te_circuit *mpls_te_circuit_new()
/* Copy SUB TLVs parameters into a buffer - No space verification are performed
*/
/* Caller must verify before that there is enough free space in the buffer */
u_char add_te_subtlvs(u_char *buf, struct mpls_te_circuit *mtc)
uint8_t add_te_subtlvs(uint8_t *buf, struct mpls_te_circuit *mtc)
{
u_char size, *tlvs = buf;
uint8_t size, *tlvs = buf;
zlog_debug("ISIS MPLS-TE: Add TE Sub TLVs to buffer");
@ -232,7 +232,7 @@ u_char add_te_subtlvs(u_char *buf, struct mpls_te_circuit *mtc)
}
/* Compute total Sub-TLVs size */
u_char subtlvs_len(struct mpls_te_circuit *mtc)
uint8_t subtlvs_len(struct mpls_te_circuit *mtc)
{
int length = 0;
@ -306,7 +306,7 @@ u_char subtlvs_len(struct mpls_te_circuit *mtc)
return 0;
}
mtc->length = (u_char)length;
mtc->length = (uint8_t)length;
return mtc->length;
}
@ -546,13 +546,9 @@ void isis_link_params_update(struct isis_circuit *circuit,
if ((SUBTLV_TYPE(mtc->rmt_ipaddr) == 0)
&& (circuit->circ_type == CIRCUIT_T_P2P)) {
struct isis_adjacency *adj = circuit->u.p2p.neighbor;
if (adj->ipv4_addrs != NULL
&& listcount(adj->ipv4_addrs) != 0) {
struct in_addr *ip_addr;
ip_addr = (struct in_addr *)listgetdata(
(struct listnode *)listhead(
adj->ipv4_addrs));
set_circuitparams_rmt_ipaddr(mtc, *ip_addr);
if (adj->ipv4_address_count) {
set_circuitparams_rmt_ipaddr(
mtc, adj->ipv4_addresses[0]);
}
}
@ -670,163 +666,116 @@ void isis_mpls_te_update(struct interface *ifp)
* Followings are vty session control functions.
*------------------------------------------------------------------------*/
static u_char show_vty_subtlv_admin_grp(struct vty *vty,
struct te_subtlv_admin_grp *tlv)
static u_char print_subtlv_admin_grp(struct sbuf *buf, int indent,
struct te_subtlv_admin_grp *tlv)
{
if (vty != NULL)
vty_out(vty, " Administrative Group: 0x%x\n",
(u_int32_t)ntohl(tlv->value));
else
zlog_debug(" Administrative Group: 0x%x",
(u_int32_t)ntohl(tlv->value));
sbuf_push(buf, indent, "Administrative Group: 0x%" PRIx32 "\n",
ntohl(tlv->value));
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_llri(struct vty *vty, struct te_subtlv_llri *tlv)
static u_char print_subtlv_llri(struct sbuf *buf, int indent,
struct te_subtlv_llri *tlv)
{
if (vty != NULL) {
vty_out(vty, " Link Local ID: %d\n",
(u_int32_t)ntohl(tlv->local));
vty_out(vty, " Link Remote ID: %d\n",
(u_int32_t)ntohl(tlv->remote));
} else {
zlog_debug(" Link Local ID: %d",
(u_int32_t)ntohl(tlv->local));
zlog_debug(" Link Remote ID: %d",
(u_int32_t)ntohl(tlv->remote));
}
sbuf_push(buf, indent, "Link Local ID: %" PRIu32 "\n",
ntohl(tlv->local));
sbuf_push(buf, indent, "Link Remote ID: %" PRIu32 "\n",
ntohl(tlv->remote));
return (SUBTLV_HDR_SIZE + TE_SUBTLV_LLRI_SIZE);
}
static u_char show_vty_subtlv_local_ipaddr(struct vty *vty,
struct te_subtlv_local_ipaddr *tlv)
static u_char print_subtlv_local_ipaddr(struct sbuf *buf, int indent,
struct te_subtlv_local_ipaddr *tlv)
{
if (vty != NULL)
vty_out(vty, " Local Interface IP Address(es): %s\n",
inet_ntoa(tlv->value));
else
zlog_debug(" Local Interface IP Address(es): %s",
inet_ntoa(tlv->value));
sbuf_push(buf, indent, "Local Interface IP Address(es): %s\n",
inet_ntoa(tlv->value));
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_rmt_ipaddr(struct vty *vty,
struct te_subtlv_rmt_ipaddr *tlv)
static u_char print_subtlv_rmt_ipaddr(struct sbuf *buf, int indent,
struct te_subtlv_rmt_ipaddr *tlv)
{
if (vty != NULL)
vty_out(vty, " Remote Interface IP Address(es): %s\n",
inet_ntoa(tlv->value));
else
zlog_debug(" Remote Interface IP Address(es): %s",
inet_ntoa(tlv->value));
sbuf_push(buf, indent, "Remote Interface IP Address(es): %s\n",
inet_ntoa(tlv->value));
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_max_bw(struct vty *vty,
struct te_subtlv_max_bw *tlv)
static u_char print_subtlv_max_bw(struct sbuf *buf, int indent,
struct te_subtlv_max_bw *tlv)
{
float fval;
fval = ntohf(tlv->value);
if (vty != NULL)
vty_out(vty, " Maximum Bandwidth: %g (Bytes/sec)\n", fval);
else
zlog_debug(" Maximum Bandwidth: %g (Bytes/sec)", fval);
sbuf_push(buf, indent, "Maximum Bandwidth: %g (Bytes/sec)\n", fval);
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_max_rsv_bw(struct vty *vty,
struct te_subtlv_max_rsv_bw *tlv)
static u_char print_subtlv_max_rsv_bw(struct sbuf *buf, int indent,
struct te_subtlv_max_rsv_bw *tlv)
{
float fval;
fval = ntohf(tlv->value);
if (vty != NULL)
vty_out(vty,
" Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
fval);
else
zlog_debug(" Maximum Reservable Bandwidth: %g (Bytes/sec)",
fval);
sbuf_push(buf, indent, "Maximum Reservable Bandwidth: %g (Bytes/sec)\n", fval);
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_unrsv_bw(struct vty *vty,
struct te_subtlv_unrsv_bw *tlv)
static u_char print_subtlv_unrsv_bw(struct sbuf *buf, int indent,
struct te_subtlv_unrsv_bw *tlv)
{
float fval1, fval2;
int i;
if (vty != NULL)
vty_out(vty, " Unreserved Bandwidth:\n");
else
zlog_debug(" Unreserved Bandwidth:");
sbuf_push(buf, indent, "Unreserved Bandwidth:\n");
for (i = 0; i < MAX_CLASS_TYPE; i += 2) {
fval1 = ntohf(tlv->value[i]);
fval2 = ntohf(tlv->value[i + 1]);
if (vty != NULL)
vty_out(vty,
" [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
i, fval1, i + 1, fval2);
else
zlog_debug(
" [%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)",
i, fval1, i + 1, fval2);
sbuf_push(buf, indent + 2, "[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
i, fval1, i + 1, fval2);
}
return (SUBTLV_HDR_SIZE + TE_SUBTLV_UNRSV_SIZE);
}
static u_char show_vty_subtlv_te_metric(struct vty *vty,
struct te_subtlv_te_metric *tlv)
static u_char print_subtlv_te_metric(struct sbuf *buf, int indent,
struct te_subtlv_te_metric *tlv)
{
u_int32_t te_metric;
te_metric = tlv->value[2] | tlv->value[1] << 8 | tlv->value[0] << 16;
if (vty != NULL)
vty_out(vty, " Traffic Engineering Metric: %u\n", te_metric);
else
zlog_debug(" Traffic Engineering Metric: %u", te_metric);
sbuf_push(buf, indent, "Traffic Engineering Metric: %u\n", te_metric);
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_ras(struct vty *vty, struct te_subtlv_ras *tlv)
static u_char print_subtlv_ras(struct sbuf *buf, int indent,
struct te_subtlv_ras *tlv)
{
if (vty != NULL)
vty_out(vty, " Inter-AS TE Remote AS number: %u\n",
ntohl(tlv->value));
else
zlog_debug(" Inter-AS TE Remote AS number: %u",
ntohl(tlv->value));
sbuf_push(buf, indent, "Inter-AS TE Remote AS number: %" PRIu32 "\n",
ntohl(tlv->value));
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_rip(struct vty *vty, struct te_subtlv_rip *tlv)
static u_char print_subtlv_rip(struct sbuf *buf, int indent,
struct te_subtlv_rip *tlv)
{
if (vty != NULL)
vty_out(vty, " Inter-AS TE Remote ASBR IP address: %s\n",
inet_ntoa(tlv->value));
else
zlog_debug(" Inter-AS TE Remote ASBR IP address: %s",
inet_ntoa(tlv->value));
sbuf_push(buf, indent, "Inter-AS TE Remote ASBR IP address: %s\n",
inet_ntoa(tlv->value));
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_av_delay(struct vty *vty,
struct te_subtlv_av_delay *tlv)
static u_char print_subtlv_av_delay(struct sbuf *buf, int indent,
struct te_subtlv_av_delay *tlv)
{
u_int32_t delay;
u_int32_t A;
@ -834,18 +783,14 @@ static u_char show_vty_subtlv_av_delay(struct vty *vty,
delay = (u_int32_t)ntohl(tlv->value) & TE_EXT_MASK;
A = (u_int32_t)ntohl(tlv->value) & TE_EXT_ANORMAL;
if (vty != NULL)
vty_out(vty, " %s Average Link Delay: %d (micro-sec)\n",
A ? "Anomalous" : "Normal", delay);
else
zlog_debug(" %s Average Link Delay: %d (micro-sec)",
A ? "Anomalous" : "Normal", delay);
sbuf_push(buf, indent, "%s Average Link Delay: %" PRIu32 " (micro-sec)\n",
A ? "Anomalous" : "Normal", delay);
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_mm_delay(struct vty *vty,
struct te_subtlv_mm_delay *tlv)
static u_char print_subtlv_mm_delay(struct sbuf *buf, int indent,
struct te_subtlv_mm_delay *tlv)
{
u_int32_t low, high;
u_int32_t A;
@ -854,33 +799,26 @@ static u_char show_vty_subtlv_mm_delay(struct vty *vty,
A = (u_int32_t)ntohl(tlv->low) & TE_EXT_ANORMAL;
high = (u_int32_t)ntohl(tlv->high) & TE_EXT_MASK;
if (vty != NULL)
vty_out(vty, " %s Min/Max Link Delay: %d / %d (micro-sec)\n",
A ? "Anomalous" : "Normal", low, high);
else
zlog_debug(" %s Min/Max Link Delay: %d / %d (micro-sec)",
A ? "Anomalous" : "Normal", low, high);
sbuf_push(buf, indent, "%s Min/Max Link Delay: %" PRIu32 " / %" PRIu32 " (micro-sec)\n",
A ? "Anomalous" : "Normal", low, high);
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_delay_var(struct vty *vty,
struct te_subtlv_delay_var *tlv)
static u_char print_subtlv_delay_var(struct sbuf *buf, int indent,
struct te_subtlv_delay_var *tlv)
{
u_int32_t jitter;
jitter = (u_int32_t)ntohl(tlv->value) & TE_EXT_MASK;
if (vty != NULL)
vty_out(vty, " Delay Variation: %d (micro-sec)\n", jitter);
else
zlog_debug(" Delay Variation: %d (micro-sec)", jitter);
sbuf_push(buf, indent, "Delay Variation: %" PRIu32 " (micro-sec)\n", jitter);
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_pkt_loss(struct vty *vty,
struct te_subtlv_pkt_loss *tlv)
static u_char print_subtlv_pkt_loss(struct sbuf *buf, int indent,
struct te_subtlv_pkt_loss *tlv)
{
u_int32_t loss;
u_int32_t A;
@ -890,189 +828,162 @@ static u_char show_vty_subtlv_pkt_loss(struct vty *vty,
fval = (float)(loss * LOSS_PRECISION);
A = (u_int32_t)ntohl(tlv->value) & TE_EXT_ANORMAL;
if (vty != NULL)
vty_out(vty, " %s Link Packet Loss: %g (%%)\n",
A ? "Anomalous" : "Normal", fval);
else
zlog_debug(" %s Link Packet Loss: %g (%%)",
A ? "Anomalous" : "Normal", fval);
sbuf_push(buf, indent, "%s Link Packet Loss: %g (%%)\n",
A ? "Anomalous" : "Normal", fval);
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_res_bw(struct vty *vty,
struct te_subtlv_res_bw *tlv)
static u_char print_subtlv_res_bw(struct sbuf *buf, int indent,
struct te_subtlv_res_bw *tlv)
{
float fval;
fval = ntohf(tlv->value);
if (vty != NULL)
vty_out(vty,
" Unidirectional Residual Bandwidth: %g (Bytes/sec)\n",
fval);
else
zlog_debug(
" Unidirectional Residual Bandwidth: %g (Bytes/sec)",
fval);
sbuf_push(buf, indent, "Unidirectional Residual Bandwidth: %g (Bytes/sec)\n",
fval);
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_ava_bw(struct vty *vty,
struct te_subtlv_ava_bw *tlv)
static u_char print_subtlv_ava_bw(struct sbuf *buf, int indent,
struct te_subtlv_ava_bw *tlv)
{
float fval;
fval = ntohf(tlv->value);
if (vty != NULL)
vty_out(vty,
" Unidirectional Available Bandwidth: %g (Bytes/sec)\n",
fval);
else
zlog_debug(
" Unidirectional Available Bandwidth: %g (Bytes/sec)",
fval);
sbuf_push(buf, indent, "Unidirectional Available Bandwidth: %g (Bytes/sec)\n",
fval);
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_subtlv_use_bw(struct vty *vty,
struct te_subtlv_use_bw *tlv)
static u_char print_subtlv_use_bw(struct sbuf *buf, int indent,
struct te_subtlv_use_bw *tlv)
{
float fval;
fval = ntohf(tlv->value);
if (vty != NULL)
vty_out(vty,
" Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n",
fval);
else
zlog_debug(
" Unidirectional Utilized Bandwidth: %g (Bytes/sec)",
fval);
sbuf_push(buf, indent, "Unidirectional Utilized Bandwidth: %g (Bytes/sec)\n",
fval);
return (SUBTLV_HDR_SIZE + SUBTLV_DEF_SIZE);
}
static u_char show_vty_unknown_tlv(struct vty *vty, struct subtlv_header *tlvh)
static u_char print_unknown_tlv(struct sbuf *buf, int indent,
struct subtlv_header *tlvh)
{
int i, rtn = 1;
u_char *v = (u_char *)tlvh;
if (vty != NULL) {
if (tlvh->length != 0) {
vty_out(vty,
" Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
tlvh->type, tlvh->length);
vty_out(vty, " Dump: [00]");
rtn = 1; /* initialize end of line counter */
for (i = 0; i < tlvh->length; i++) {
vty_out(vty, " %#.2x", v[i]);
if (rtn == 8) {
vty_out(vty, "\n [%.2x]",
i + 1);
rtn = 1;
} else
rtn++;
}
vty_out(vty, "\n");
} else
vty_out(vty,
" Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
tlvh->type, tlvh->length);
if (tlvh->length != 0) {
sbuf_push(buf, indent,
"Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
tlvh->type, tlvh->length);
sbuf_push(buf, indent + 2, "Dump: [00]");
rtn = 1; /* initialize end of line counter */
for (i = 0; i < tlvh->length; i++) {
sbuf_push(buf, 0, " %#.2x", v[i]);
if (rtn == 8) {
sbuf_push(buf, 0, "\n");
sbuf_push(buf, indent + 8,
"[%.2x]", i + 1);
rtn = 1;
} else
rtn++;
}
sbuf_push(buf, 0, "\n");
} else {
zlog_debug(" Unknown TLV: [type(%#.2x), length(%#.2x)]",
tlvh->type, tlvh->length);
sbuf_push(buf, indent,
"Unknown TLV: [type(%#.2x), length(%#.2x)]\n",
tlvh->type, tlvh->length);
}
return SUBTLV_SIZE(tlvh);
}
/* Main Show function */
void mpls_te_print_detail(struct vty *vty, struct te_is_neigh *te)
void mpls_te_print_detail(struct sbuf *buf, int indent,
uint8_t *subtlvs, uint8_t subtlv_len)
{
struct subtlv_header *tlvh;
u_int16_t sum = 0;
struct subtlv_header *tlvh = (struct subtlv_header *)subtlvs;
uint16_t sum = 0;
zlog_debug("ISIS MPLS-TE: Show database TE detail");
tlvh = (struct subtlv_header *)te->sub_tlvs;
for (; sum < te->sub_tlvs_length; tlvh = SUBTLV_HDR_NEXT(tlvh)) {
for (; sum < subtlv_len; tlvh = SUBTLV_HDR_NEXT(tlvh)) {
switch (tlvh->type) {
case TE_SUBTLV_ADMIN_GRP:
sum += show_vty_subtlv_admin_grp(
vty, (struct te_subtlv_admin_grp *)tlvh);
sum += print_subtlv_admin_grp(buf, indent,
(struct te_subtlv_admin_grp *)tlvh);
break;
case TE_SUBTLV_LLRI:
sum += show_vty_subtlv_llri(
vty, (struct te_subtlv_llri *)tlvh);
sum += print_subtlv_llri(buf, indent,
(struct te_subtlv_llri *)tlvh);
break;
case TE_SUBTLV_LOCAL_IPADDR:
sum += show_vty_subtlv_local_ipaddr(
vty, (struct te_subtlv_local_ipaddr *)tlvh);
sum += print_subtlv_local_ipaddr(buf, indent,
(struct te_subtlv_local_ipaddr *)tlvh);
break;
case TE_SUBTLV_RMT_IPADDR:
sum += show_vty_subtlv_rmt_ipaddr(
vty, (struct te_subtlv_rmt_ipaddr *)tlvh);
sum += print_subtlv_rmt_ipaddr(buf, indent,
(struct te_subtlv_rmt_ipaddr *)tlvh);
break;
case TE_SUBTLV_MAX_BW:
sum += show_vty_subtlv_max_bw(
vty, (struct te_subtlv_max_bw *)tlvh);
sum += print_subtlv_max_bw(buf, indent,
(struct te_subtlv_max_bw *)tlvh);
break;
case TE_SUBTLV_MAX_RSV_BW:
sum += show_vty_subtlv_max_rsv_bw(
vty, (struct te_subtlv_max_rsv_bw *)tlvh);
sum += print_subtlv_max_rsv_bw(buf, indent,
(struct te_subtlv_max_rsv_bw *)tlvh);
break;
case TE_SUBTLV_UNRSV_BW:
sum += show_vty_subtlv_unrsv_bw(
vty, (struct te_subtlv_unrsv_bw *)tlvh);
sum += print_subtlv_unrsv_bw(buf, indent,
(struct te_subtlv_unrsv_bw *)tlvh);
break;
case TE_SUBTLV_TE_METRIC:
sum += show_vty_subtlv_te_metric(
vty, (struct te_subtlv_te_metric *)tlvh);
sum += print_subtlv_te_metric(buf, indent,
(struct te_subtlv_te_metric *)tlvh);
break;
case TE_SUBTLV_RAS:
sum += show_vty_subtlv_ras(
vty, (struct te_subtlv_ras *)tlvh);
sum += print_subtlv_ras(buf, indent,
(struct te_subtlv_ras *)tlvh);
break;
case TE_SUBTLV_RIP:
sum += show_vty_subtlv_rip(
vty, (struct te_subtlv_rip *)tlvh);
sum += print_subtlv_rip(buf, indent,
(struct te_subtlv_rip *)tlvh);
break;
case TE_SUBTLV_AV_DELAY:
sum += show_vty_subtlv_av_delay(
vty, (struct te_subtlv_av_delay *)tlvh);
sum += print_subtlv_av_delay(buf, indent,
(struct te_subtlv_av_delay *)tlvh);
break;
case TE_SUBTLV_MM_DELAY:
sum += show_vty_subtlv_mm_delay(
vty, (struct te_subtlv_mm_delay *)tlvh);
sum += print_subtlv_mm_delay(buf, indent,
(struct te_subtlv_mm_delay *)tlvh);
break;
case TE_SUBTLV_DELAY_VAR:
sum += show_vty_subtlv_delay_var(
vty, (struct te_subtlv_delay_var *)tlvh);
sum += print_subtlv_delay_var(buf, indent,
(struct te_subtlv_delay_var *)tlvh);
break;
case TE_SUBTLV_PKT_LOSS:
sum += show_vty_subtlv_pkt_loss(
vty, (struct te_subtlv_pkt_loss *)tlvh);
sum += print_subtlv_pkt_loss(buf, indent,
(struct te_subtlv_pkt_loss *)tlvh);
break;
case TE_SUBTLV_RES_BW:
sum += show_vty_subtlv_res_bw(
vty, (struct te_subtlv_res_bw *)tlvh);
sum += print_subtlv_res_bw(buf, indent,
(struct te_subtlv_res_bw *)tlvh);
break;
case TE_SUBTLV_AVA_BW:
sum += show_vty_subtlv_ava_bw(
vty, (struct te_subtlv_ava_bw *)tlvh);
sum += print_subtlv_ava_bw(buf, indent,
(struct te_subtlv_ava_bw *)tlvh);
break;
case TE_SUBTLV_USE_BW:
sum += show_vty_subtlv_use_bw(
vty, (struct te_subtlv_use_bw *)tlvh);
sum += print_subtlv_use_bw(buf, indent,
(struct te_subtlv_use_bw *)tlvh);
break;
default:
sum += show_vty_unknown_tlv(vty, tlvh);
sum += print_unknown_tlv(buf, indent, tlvh);
break;
}
}
@ -1256,6 +1167,9 @@ DEFUN (show_isis_mpls_te_router,
static void show_mpls_te_sub(struct vty *vty, struct interface *ifp)
{
struct mpls_te_circuit *mtc;
struct sbuf buf;
sbuf_init(&buf, NULL, 0);
if ((IS_MPLS_TE(isisMplsTE))
&& ((mtc = lookup_mpls_params_by_ifp(ifp)) != NULL)) {
@ -1280,38 +1194,42 @@ static void show_mpls_te_sub(struct vty *vty, struct interface *ifp)
ifp->name);
}
show_vty_subtlv_admin_grp(vty, &mtc->admin_grp);
sbuf_reset(&buf);
print_subtlv_admin_grp(&buf, 4, &mtc->admin_grp);
if (SUBTLV_TYPE(mtc->local_ipaddr) != 0)
show_vty_subtlv_local_ipaddr(vty, &mtc->local_ipaddr);
print_subtlv_local_ipaddr(&buf, 4, &mtc->local_ipaddr);
if (SUBTLV_TYPE(mtc->rmt_ipaddr) != 0)
show_vty_subtlv_rmt_ipaddr(vty, &mtc->rmt_ipaddr);
print_subtlv_rmt_ipaddr(&buf, 4, &mtc->rmt_ipaddr);
show_vty_subtlv_max_bw(vty, &mtc->max_bw);
show_vty_subtlv_max_rsv_bw(vty, &mtc->max_rsv_bw);
show_vty_subtlv_unrsv_bw(vty, &mtc->unrsv_bw);
show_vty_subtlv_te_metric(vty, &mtc->te_metric);
print_subtlv_max_bw(&buf, 4, &mtc->max_bw);
print_subtlv_max_rsv_bw(&buf, 4, &mtc->max_rsv_bw);
print_subtlv_unrsv_bw(&buf, 4, &mtc->unrsv_bw);
print_subtlv_te_metric(&buf, 4, &mtc->te_metric);
if (IS_INTER_AS(mtc->type)) {
if (SUBTLV_TYPE(mtc->ras) != 0)
show_vty_subtlv_ras(vty, &mtc->ras);
print_subtlv_ras(&buf, 4, &mtc->ras);
if (SUBTLV_TYPE(mtc->rip) != 0)
show_vty_subtlv_rip(vty, &mtc->rip);
print_subtlv_rip(&buf, 4, &mtc->rip);
}
show_vty_subtlv_av_delay(vty, &mtc->av_delay);
show_vty_subtlv_mm_delay(vty, &mtc->mm_delay);
show_vty_subtlv_delay_var(vty, &mtc->delay_var);
show_vty_subtlv_pkt_loss(vty, &mtc->pkt_loss);
show_vty_subtlv_res_bw(vty, &mtc->res_bw);
show_vty_subtlv_ava_bw(vty, &mtc->ava_bw);
show_vty_subtlv_use_bw(vty, &mtc->use_bw);
print_subtlv_av_delay(&buf, 4, &mtc->av_delay);
print_subtlv_mm_delay(&buf, 4, &mtc->mm_delay);
print_subtlv_delay_var(&buf, 4, &mtc->delay_var);
print_subtlv_pkt_loss(&buf, 4, &mtc->pkt_loss);
print_subtlv_res_bw(&buf, 4, &mtc->res_bw);
print_subtlv_ava_bw(&buf, 4, &mtc->ava_bw);
print_subtlv_use_bw(&buf, 4, &mtc->use_bw);
vty_multiline(vty, "", "%s", sbuf_buf(&buf));
vty_out(vty, "---------------\n\n");
} else {
vty_out(vty, " %s: MPLS-TE is disabled on this interface\n",
ifp->name);
}
sbuf_free(&buf);
return;
}

View File

@ -81,6 +81,8 @@ struct subtlv_header {
u_char length; /* Value portion only, in byte */
};
#define MAX_SUBTLV_SIZE 256
#define SUBTLV_HDR_SIZE 2 /* (sizeof (struct sub_tlv_header)) */
#define SUBTLV_SIZE(stlvh) (SUBTLV_HDR_SIZE + (stlvh)->length)
@ -306,12 +308,13 @@ struct mpls_te_circuit {
/* Prototypes. */
void isis_mpls_te_init(void);
struct mpls_te_circuit *mpls_te_circuit_new(void);
void mpls_te_print_detail(struct vty *, struct te_is_neigh *);
struct sbuf;
void mpls_te_print_detail(struct sbuf *buf, int indent, uint8_t *subtlvs, uint8_t subtlv_len);
void set_circuitparams_local_ipaddr(struct mpls_te_circuit *, struct in_addr);
void set_circuitparams_rmt_ipaddr(struct mpls_te_circuit *, struct in_addr);
u_char subtlvs_len(struct mpls_te_circuit *);
u_char add_te_subtlvs(u_char *, struct mpls_te_circuit *);
u_char build_te_subtlvs(u_char *, struct isis_circuit *);
uint8_t subtlvs_len(struct mpls_te_circuit *);
uint8_t add_te_subtlvs(uint8_t *, struct mpls_te_circuit *);
uint8_t build_te_subtlvs(uint8_t *, struct isis_circuit *);
void isis_link_params_update(struct isis_circuit *, struct interface *);
void isis_mpls_te_update(struct interface *);
void isis_mpls_te_config_write_router(struct vty *);

File diff suppressed because it is too large Load Diff

View File

@ -1,340 +0,0 @@
/*
* IS-IS Rout(e)ing protocol - isis_tlv.h
* IS-IS TLV related routines
*
* Copyright (C) 2001,2002 Sampo Saaristo
* Tampere University of Technology
* Institute of Communications Engineering
*
* 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
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_ISIS_TLV_H
#define _ZEBRA_ISIS_TLV_H
#include "isisd/isis_mt.h"
/*
* The list of TLVs we (should) support.
* ____________________________________________________________________________
* Name Value IIH LSP SNP Status
* LAN
* ____________________________________________________________________________
*
* Area Addresses 1 y y n ISO10589
* IIS Neighbors 2 n y n ISO10589
* ES Neighbors 3 n y n ISO10589
* IIS Neighbors 6 y n n ISO10589
* Padding 8 y n n ISO10589
* LSP Entries 9 n n y ISO10589
* Authentication 10 y y y ISO10589, RFC3567
* Checksum 12 y n y RFC3358
* Extended IS Reachability 22 n y n RFC5305
* IS Alias 24 n y n RFC3786
* IP Int. Reachability 128 n y n RFC1195
* Protocols Supported 129 y y n RFC1195
* IP Ext. Reachability 130 n y n RFC1195
* IDRPI 131 n y y RFC1195
* IP Interface Address 132 y y n RFC1195
* TE Router ID 134 n y n RFC5305
* Extended IP Reachability 135 n y n RFC5305
* Dynamic Hostname 137 n y n RFC2763
* Shared Risk Link Group 138 n y y RFC5307
* Inter-AS Reachability 141 n y n RFC5316
* Restart TLV 211 y n n RFC3847
* MT IS Reachability 222 n y n RFC5120
* MT Supported 229 y y n RFC5120
* IPv6 Interface Address 232 y y n RFC5308
* MT IP Reachability 235 n y n RFC5120
* IPv6 IP Reachability 236 n y n RFC5308
* MT IPv6 IP Reachability 237 n y n RFC5120
* P2P Adjacency State 240 y n n RFC3373
* IIH Sequence Number 241 y n n draft-shen-isis-iih-sequence
* Router Capability 242 n y n RFC4971
*
*
* IS Reachability sub-TLVs we support (See isis_te.[c,h])
* ____________________________________________________________________________
* Name Value Status
* ____________________________________________________________________________
* Administartive group (color) 3 RFC5305
* Link Local/Remote Identifiers 4 RFC5307
* IPv4 interface address 6 RFC5305
* IPv4 neighbor address 8 RFC5305
* Maximum link bandwidth 9 RFC5305
* Reservable link bandwidth 10 RFC5305
* Unreserved bandwidth 11 RFC5305
* TE Default metric 18 RFC5305
* Link Protection Type 20 RFC5307
* Interface Switching Capability 21 RFC5307
* Remote AS number 24 RFC5316
* IPv4 Remote ASBR identifier 25 RFC5316
*
*
* IP Reachability sub-TLVs we (should) support.
* ____________________________________________________________________________
* Name Value Status
* ____________________________________________________________________________
* 32bit administrative tag 1 RFC5130
* 64bit administrative tag 2 RFC5130
* Management prefix color 117 RFC5120
*/
#define AREA_ADDRESSES 1
#define IS_NEIGHBOURS 2
#define ES_NEIGHBOURS 3
#define LAN_NEIGHBOURS 6
#define PADDING 8
#define LSP_ENTRIES 9
#define AUTH_INFO 10
#define CHECKSUM 12
#define TE_IS_NEIGHBOURS 22
#define IS_ALIAS 24
#define IPV4_INT_REACHABILITY 128
#define PROTOCOLS_SUPPORTED 129
#define IPV4_EXT_REACHABILITY 130
#define IDRP_INFO 131
#define IPV4_ADDR 132
#define TE_ROUTER_ID 134
#define TE_IPV4_REACHABILITY 135
#define DYNAMIC_HOSTNAME 137
#define GRACEFUL_RESTART 211
#define MT_IS_NEIGHBOURS 222
#define MT_ROUTER_INFORMATION 229
#define IPV6_ADDR 232
#define MT_IPV4_REACHABILITY 235
#define IPV6_REACHABILITY 236
#define MT_IPV6_REACHABILITY 237
#define WAY3_HELLO 240
#define ROUTER_INFORMATION 242
#define AUTH_INFO_HDRLEN 3
#define MAX_TLV_LEN 255
#define IS_NEIGHBOURS_LEN (ISIS_SYS_ID_LEN + 5)
#define LAN_NEIGHBOURS_LEN 6
#define LSP_ENTRIES_LEN (10 + ISIS_SYS_ID_LEN) /* FIXME: should be entry */
#define IPV4_REACH_LEN 12
#define IPV6_REACH_LEN 22
#define TE_IPV4_REACH_LEN 9
#define MAX_SUBTLV_SIZE 256
/* struct for neighbor */
struct is_neigh {
struct metric metrics;
u_char neigh_id[ISIS_SYS_ID_LEN + 1];
};
/* struct for te metric */
struct te_is_neigh {
u_char neigh_id[ISIS_SYS_ID_LEN + 1];
u_char te_metric[3];
u_char sub_tlvs_length;
/* Theorical Maximum SubTLVs is 256 because the sub_tlvs_length is 8
* bits */
/* Practically, 118 bytes are necessary to store all supported TE
* parameters */
/* FIXME: A pointer will use less memory, but need to be free */
/* which is hard to fix, especially within free_tlvs() function */
/* and malloc() / free() as a CPU cost compared to the memory usage */
u_char sub_tlvs[MAX_SUBTLV_SIZE]; /* SUB TLVs storage */
};
/* Decode and encode three-octet metric into host byte order integer */
#define GET_TE_METRIC(t) \
(((unsigned)(t)->te_metric[0] << 16) | ((t)->te_metric[1] << 8) \
| (t)->te_metric[2])
#define SET_TE_METRIC(t, m) \
(((t)->te_metric[0] = (m) >> 16), ((t)->te_metric[1] = (m) >> 8), \
((t)->te_metric[2] = (m)))
/* struct for es neighbors */
struct es_neigh {
struct metric metrics;
/* approximate position of first, we use the
* length ((uchar*)metric-1) to know all */
u_char first_es_neigh[ISIS_SYS_ID_LEN];
};
struct partition_desig_level2_is {
struct list *isis_system_ids;
};
/* struct for lan neighbors */
struct lan_neigh {
u_char LAN_addr[6];
};
#ifdef __SUNPRO_C
#pragma pack(1)
#endif
/* struct for LSP entry */
struct lsp_entry {
u_int16_t rem_lifetime;
u_char lsp_id[ISIS_SYS_ID_LEN + 2];
u_int32_t seq_num;
u_int16_t checksum;
} __attribute__((packed));
#ifdef __SUNPRO_C
#pragma pack()
#endif
/* struct for checksum */
struct checksum {
u_int16_t checksum;
};
/* ipv4 reachability */
struct ipv4_reachability {
struct metric metrics;
struct in_addr prefix;
struct in_addr mask;
};
/* te router id */
struct te_router_id {
struct in_addr id;
};
/* te ipv4 reachability */
struct te_ipv4_reachability {
u_int32_t te_metric;
u_char control;
u_char prefix_start; /* since this is variable length by nature it only
*/
}; /* points to an approximate location */
#define TE_IPV4_HAS_SUBTLV (0x40)
struct idrp_info {
u_char len;
u_char *value;
};
struct ipv6_reachability {
u_int32_t metric;
u_char control_info;
u_char prefix_len;
u_char prefix[16];
};
/* bits in control_info */
#define CTRL_INFO_DIRECTION 0x80
#define DIRECTION_UP 0x00
#define DIRECTION_DOWN 0x80
#define CTRL_INFO_DISTRIBUTION 0x40
#define DISTRIBUTION_INTERNAL 0x00
#define DISTRIBUTION_EXTERNAL 0x40
#define CTRL_INFO_SUBTLVS 0x20
struct mt_router_info {
ISIS_MT_INFO_FIELDS
bool overload;
};
/*
* Pointer to each tlv type, filled by parse_tlvs()
*/
struct tlvs {
struct checksum *checksum;
struct hostname *hostname;
struct nlpids *nlpids;
struct te_router_id *router_id;
struct list *area_addrs;
struct list *mt_router_info;
struct list *is_neighs;
struct list *te_is_neighs;
struct list *mt_is_neighs;
struct list *es_neighs;
struct list *lsp_entries;
struct list *prefix_neighs;
struct list *lan_neighs;
struct list *ipv4_addrs;
struct list *ipv4_int_reachs;
struct list *ipv4_ext_reachs;
struct list *te_ipv4_reachs;
struct list *mt_ipv4_reachs;
struct list *ipv6_addrs;
struct list *ipv6_reachs;
struct list *mt_ipv6_reachs;
struct isis_passwd auth_info;
};
/*
* Own definitions - used to bitmask found and expected
*/
#define TLVFLAG_AREA_ADDRS (1<<0)
#define TLVFLAG_IS_NEIGHS (1<<1)
#define TLVFLAG_ES_NEIGHS (1<<2)
#define TLVFLAG_PARTITION_DESIG_LEVEL2_IS (1<<3)
#define TLVFLAG_PREFIX_NEIGHS (1<<4)
#define TLVFLAG_LAN_NEIGHS (1<<5)
#define TLVFLAG_LSP_ENTRIES (1<<6)
#define TLVFLAG_PADDING (1<<7)
#define TLVFLAG_AUTH_INFO (1<<8)
#define TLVFLAG_IPV4_INT_REACHABILITY (1<<9)
#define TLVFLAG_NLPID (1<<10)
#define TLVFLAG_IPV4_EXT_REACHABILITY (1<<11)
#define TLVFLAG_IPV4_ADDR (1<<12)
#define TLVFLAG_DYN_HOSTNAME (1<<13)
#define TLVFLAG_IPV6_ADDR (1<<14)
#define TLVFLAG_IPV6_REACHABILITY (1<<15)
#define TLVFLAG_TE_IS_NEIGHS (1<<16)
#define TLVFLAG_TE_IPV4_REACHABILITY (1<<17)
#define TLVFLAG_3WAY_HELLO (1<<18)
#define TLVFLAG_TE_ROUTER_ID (1<<19)
#define TLVFLAG_CHECKSUM (1<<20)
#define TLVFLAG_GRACEFUL_RESTART (1<<21)
#define TLVFLAG_MT_ROUTER_INFORMATION (1<<22)
void init_tlvs(struct tlvs *tlvs, uint32_t expected);
void free_tlvs(struct tlvs *tlvs);
int parse_tlvs(char *areatag, u_char *stream, int size, u_int32_t *expected,
u_int32_t *found, struct tlvs *tlvs, u_int32_t *auth_tlv_offset);
int add_tlv(u_char, u_char, u_char *, struct stream *);
void free_tlv(void *val);
int tlv_add_mt_router_info(struct list *mt_router_info, struct stream *stream);
int tlv_add_area_addrs(struct list *area_addrs, struct stream *stream);
int tlv_add_is_neighs(struct list *is_neighs, struct stream *stream);
unsigned int tlv_add_te_is_neighs(struct list *te_is_neighs,
struct stream *stream, void *arg);
int tlv_add_lan_neighs(struct list *lan_neighs, struct stream *stream);
int tlv_add_nlpid(struct nlpids *nlpids, struct stream *stream);
int tlv_add_checksum(struct checksum *checksum, struct stream *stream);
int tlv_add_authinfo(u_char auth_type, u_char authlen, u_char *auth_value,
struct stream *stream);
int tlv_add_ip_addrs(struct list *ip_addrs, struct stream *stream);
int tlv_add_in_addr(struct in_addr *, struct stream *stream, u_char tag);
int tlv_add_dynamic_hostname(struct hostname *hostname, struct stream *stream);
int tlv_add_lsp_entries(struct list *lsps, struct stream *stream);
int tlv_add_ipv4_int_reachs(struct list *ipv4_reachs, struct stream *stream);
int tlv_add_ipv4_ext_reachs(struct list *ipv4_reachs, struct stream *stream);
unsigned int tlv_add_te_ipv4_reachs(struct list *te_ipv4_reachs,
struct stream *stream, void *arg);
int tlv_add_ipv6_addrs(struct list *ipv6_addrs, struct stream *stream);
unsigned int tlv_add_ipv6_reachs(struct list *ipv6_reachs,
struct stream *stream, void *arg);
int tlv_add_padding(struct stream *stream);
#endif /* _ZEBRA_ISIS_TLV_H */

3090
isisd/isis_tlvs.c Normal file

File diff suppressed because it is too large Load Diff

308
isisd/isis_tlvs.h Normal file
View File

@ -0,0 +1,308 @@
/*
* IS-IS TLV Serializer/Deserializer
*
* Copyright (C) 2015,2017 Christian Franke
*
* This file is part of FRR.
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef ISIS_TLVS_H
#define ISIS_TLVS_H
#include "openbsd-tree.h"
#include "prefix.h"
#include "isisd/dict.h"
struct isis_subtlvs;
struct isis_area_address;
struct isis_area_address {
struct isis_area_address *next;
uint8_t addr[20];
uint8_t len;
};
struct isis_oldstyle_reach;
struct isis_oldstyle_reach {
struct isis_oldstyle_reach *next;
uint8_t id[7];
uint8_t metric;
};
struct isis_oldstyle_ip_reach;
struct isis_oldstyle_ip_reach {
struct isis_oldstyle_ip_reach *next;
uint8_t metric;
struct prefix_ipv4 prefix;
};
struct isis_lsp_entry;
struct isis_lsp_entry {
struct isis_lsp_entry *next;
uint16_t rem_lifetime;
uint8_t id[8];
uint16_t checksum;
uint32_t seqno;
struct isis_lsp *lsp;
};
struct isis_extended_reach;
struct isis_extended_reach {
struct isis_extended_reach *next;
uint8_t id[7];
uint32_t metric;
uint8_t *subtlvs;
uint8_t subtlv_len;
};
struct isis_extended_ip_reach;
struct isis_extended_ip_reach {
struct isis_extended_ip_reach *next;
uint32_t metric;
bool down;
struct prefix_ipv4 prefix;
};
struct isis_ipv6_reach;
struct isis_ipv6_reach {
struct isis_ipv6_reach *next;
uint32_t metric;
bool down;
bool external;
struct prefix_ipv6 prefix;
struct isis_subtlvs *subtlvs;
};
struct isis_protocols_supported {
uint8_t count;
uint8_t *protocols;
};
struct isis_item;
struct isis_item {
struct isis_item *next;
};
struct isis_lan_neighbor;
struct isis_lan_neighbor {
struct isis_lan_neighbor *next;
uint8_t mac[6];
};
struct isis_ipv4_address;
struct isis_ipv4_address {
struct isis_ipv4_address *next;
struct in_addr addr;
};
struct isis_ipv6_address;
struct isis_ipv6_address {
struct isis_ipv6_address *next;
struct in6_addr addr;
};
struct isis_mt_router_info;
struct isis_mt_router_info {
struct isis_mt_router_info *next;
bool overload;
bool attached;
uint16_t mtid;
};
struct isis_auth;
struct isis_auth {
struct isis_auth *next;
uint8_t type;
uint8_t length;
uint8_t value[256];
uint8_t plength;
uint8_t passwd[256];
size_t offset; /* Only valid after packing */
};
struct isis_item_list;
struct isis_item_list {
struct isis_item *head;
struct isis_item **tail;
RB_ENTRY(isis_item_list) mt_tree;
uint16_t mtid;
unsigned int count;
};
RB_HEAD(isis_mt_item_list, isis_item_list);
struct isis_item_list *isis_get_mt_items(struct isis_mt_item_list *m,
uint16_t mtid);
struct isis_item_list *isis_lookup_mt_items(struct isis_mt_item_list *m,
uint16_t mtid);
struct isis_tlvs {
struct isis_item_list isis_auth;
struct isis_item_list area_addresses;
struct isis_item_list oldstyle_reach;
struct isis_item_list lan_neighbor;
struct isis_item_list lsp_entries;
struct isis_item_list extended_reach;
struct isis_mt_item_list mt_reach;
struct isis_item_list oldstyle_ip_reach;
struct isis_protocols_supported protocols_supported;
struct isis_item_list oldstyle_ip_reach_ext;
struct isis_item_list ipv4_address;
struct isis_item_list ipv6_address;
struct isis_item_list mt_router_info;
bool mt_router_info_empty;
struct in_addr *te_router_id;
struct isis_item_list extended_ip_reach;
struct isis_mt_item_list mt_ip_reach;
char *hostname;
struct isis_item_list ipv6_reach;
struct isis_mt_item_list mt_ipv6_reach;
};
struct isis_subtlvs {
/* draft-baker-ipv6-isis-dst-src-routing-06 */
struct prefix_ipv6 *source_prefix;
};
enum isis_tlv_context {
ISIS_CONTEXT_LSP,
ISIS_CONTEXT_SUBTLV_NE_REACH,
ISIS_CONTEXT_SUBTLV_IP_REACH,
ISIS_CONTEXT_SUBTLV_IPV6_REACH,
ISIS_CONTEXT_MAX
};
enum isis_tlv_type {
ISIS_TLV_AREA_ADDRESSES = 1,
ISIS_TLV_OLDSTYLE_REACH = 2,
ISIS_TLV_LAN_NEIGHBORS = 6,
ISIS_TLV_PADDING = 8,
ISIS_TLV_LSP_ENTRY = 9,
ISIS_TLV_AUTH = 10,
ISIS_TLV_EXTENDED_REACH = 22,
ISIS_TLV_OLDSTYLE_IP_REACH = 128,
ISIS_TLV_PROTOCOLS_SUPPORTED = 129,
ISIS_TLV_OLDSTYLE_IP_REACH_EXT = 130,
ISIS_TLV_IPV4_ADDRESS = 132,
ISIS_TLV_TE_ROUTER_ID = 134,
ISIS_TLV_EXTENDED_IP_REACH = 135,
ISIS_TLV_DYNAMIC_HOSTNAME = 137,
ISIS_TLV_MT_REACH = 222,
ISIS_TLV_MT_ROUTER_INFO = 229,
ISIS_TLV_IPV6_ADDRESS = 232,
ISIS_TLV_MT_IP_REACH = 235,
ISIS_TLV_IPV6_REACH = 236,
ISIS_TLV_MT_IPV6_REACH = 237,
ISIS_TLV_MAX = 256,
ISIS_SUBTLV_IPV6_SOURCE_PREFIX = 22
};
#define IS_COMPAT_MT_TLV(tlv_type) \
((tlv_type == ISIS_TLV_MT_REACH) || (tlv_type == ISIS_TLV_MT_IP_REACH) \
|| (tlv_type == ISIS_TLV_MT_IPV6_REACH))
struct stream;
int isis_pack_tlvs(struct isis_tlvs *tlvs, struct stream *stream,
size_t len_pointer, bool pad, bool is_lsp);
void isis_free_tlvs(struct isis_tlvs *tlvs);
struct isis_tlvs *isis_alloc_tlvs(void);
int isis_unpack_tlvs(size_t avail_len, struct stream *stream,
struct isis_tlvs **dest, const char **error_log);
const char *isis_format_tlvs(struct isis_tlvs *tlvs);
struct isis_tlvs *isis_copy_tlvs(struct isis_tlvs *tlvs);
struct list *isis_fragment_tlvs(struct isis_tlvs *tlvs, size_t size);
#define ISIS_EXTENDED_IP_REACH_DOWN 0x80
#define ISIS_EXTENDED_IP_REACH_SUBTLV 0x40
#define ISIS_IPV6_REACH_DOWN 0x80
#define ISIS_IPV6_REACH_EXTERNAL 0x40
#define ISIS_IPV6_REACH_SUBTLV 0x20
#ifndef ISIS_MT_MASK
#define ISIS_MT_MASK 0x0fff
#define ISIS_MT_OL_MASK 0x8000
#define ISIS_MT_AT_MASK 0x4000
#endif
void isis_tlvs_add_auth(struct isis_tlvs *tlvs, struct isis_passwd *passwd);
void isis_tlvs_add_area_addresses(struct isis_tlvs *tlvs,
struct list *addresses);
void isis_tlvs_add_lan_neighbors(struct isis_tlvs *tlvs,
struct list *neighbors);
void isis_tlvs_set_protocols_supported(struct isis_tlvs *tlvs,
struct nlpids *nlpids);
void isis_tlvs_add_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid,
bool overload, bool attached);
void isis_tlvs_add_ipv4_address(struct isis_tlvs *tlvs, struct in_addr *addr);
void isis_tlvs_add_ipv4_addresses(struct isis_tlvs *tlvs,
struct list *addresses);
void isis_tlvs_add_ipv6_addresses(struct isis_tlvs *tlvs,
struct list *addresses);
bool isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
struct stream *stream, bool is_lsp);
bool isis_tlvs_area_addresses_match(struct isis_tlvs *tlvs,
struct list *addresses);
struct isis_adjacency;
void isis_tlvs_to_adj(struct isis_tlvs *tlvs, struct isis_adjacency *adj,
bool *changed);
bool isis_tlvs_own_snpa_found(struct isis_tlvs *tlvs, uint8_t *snpa);
void isis_tlvs_add_lsp_entry(struct isis_tlvs *tlvs, struct isis_lsp *lsp);
void isis_tlvs_add_csnp_entries(struct isis_tlvs *tlvs, uint8_t *start_id,
uint8_t *stop_id, uint16_t num_lsps,
dict_t *lspdb, struct isis_lsp **last_lsp);
void isis_tlvs_set_dynamic_hostname(struct isis_tlvs *tlvs,
const char *hostname);
void isis_tlvs_set_te_router_id(struct isis_tlvs *tlvs,
const struct in_addr *id);
void isis_tlvs_add_oldstyle_ip_reach(struct isis_tlvs *tlvs,
struct prefix_ipv4 *dest, uint8_t metric);
void isis_tlvs_add_extended_ip_reach(struct isis_tlvs *tlvs,
struct prefix_ipv4 *dest, uint32_t metric);
void isis_tlvs_add_ipv6_reach(struct isis_tlvs *tlvs, uint16_t mtid,
struct prefix_ipv6 *dest, uint32_t metric);
void isis_tlvs_add_oldstyle_reach(struct isis_tlvs *tlvs, uint8_t *id,
uint8_t metric);
void isis_tlvs_add_extended_reach(struct isis_tlvs *tlvs, uint16_t mtid,
uint8_t *id, uint32_t metric,
uint8_t *subtlvs, uint8_t subtlv_len);
struct isis_mt_router_info *
isis_tlvs_lookup_mt_router_info(struct isis_tlvs *tlvs, uint16_t mtid);
#endif

View File

@ -42,7 +42,6 @@
#include "isisd/isis_flags.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_tlv.h"
#include "isisd/isisd.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_csm.h"

View File

@ -49,7 +49,6 @@
#include "isisd/isis_pdu.h"
#include "isisd/isis_misc.h"
#include "isisd/isis_constants.h"
#include "isisd/isis_tlv.h"
#include "isisd/isis_lsp.h"
#include "isisd/isis_spf.h"
#include "isisd/isis_route.h"

View File

@ -67,7 +67,7 @@ int iso_csum_verify(u_char *buffer, int len, uint16_t csum, int offset)
return 1;
checksum = fletcher_checksum(buffer, len, offset);
if (checksum == csum)
if (checksum == htons(csum))
return 0;
return 1;
}

107
lib/sbuf.c Normal file
View File

@ -0,0 +1,107 @@
/*
* Simple string buffer
*
* Copyright (C) 2017 Christian Franke
*
* This file is part of FRR.
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <zebra.h>
#include "sbuf.h"
#include "memory.h"
void sbuf_init(struct sbuf *dest, char *buf, size_t size)
{
dest->fixed = (size > 0);
if (dest->fixed) {
dest->buf = buf;
dest->size = size;
} else {
dest->buf = XMALLOC(MTYPE_TMP, 4096);
dest->size = 4096;
}
dest->pos = 0;
dest->buf[0] = '\0';
}
void sbuf_reset(struct sbuf *dest)
{
dest->pos = 0;
dest->buf[0] = '\0';
}
const char *sbuf_buf(struct sbuf *buf)
{
return buf->buf;
}
void sbuf_free(struct sbuf *buf)
{
if (!buf->fixed)
XFREE(MTYPE_TMP, buf->buf);
}
void sbuf_push(struct sbuf *buf, int indent, const char *format, ...)
{
va_list args;
int written;
if (!buf->fixed) {
char dummy;
int written1, written2;
size_t new_size;
written1 = snprintf(&dummy, 0, "%*s", indent, "");
va_start(args, format);
written2 = vsnprintf(&dummy, 0, format, args);
va_end(args);
new_size = buf->size;
if (written1 >= 0 && written2 >= 0) {
while (buf->pos + written1 + written2 >= new_size)
new_size *= 2;
if (new_size > buf->size) {
buf->buf =
XREALLOC(MTYPE_TMP, buf->buf, new_size);
buf->size = new_size;
}
}
}
written = snprintf(buf->buf + buf->pos, buf->size - buf->pos, "%*s",
indent, "");
if (written >= 0)
buf->pos += written;
if (buf->pos > buf->size)
buf->pos = buf->size;
va_start(args, format);
written = vsnprintf(buf->buf + buf->pos, buf->size - buf->pos, format,
args);
va_end(args);
if (written >= 0)
buf->pos += written;
if (buf->pos > buf->size)
buf->pos = buf->size;
if (buf->pos == buf->size)
assert(!"Buffer filled up!");
}

77
lib/sbuf.h Normal file
View File

@ -0,0 +1,77 @@
/*
* Simple string buffer
*
* Copyright (C) 2017 Christian Franke
*
* This file is part of FRR.
*
* FRR is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* FRR is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with FRR; see the file COPYING. If not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef SBUF_H
#define SBUF_H
/*
* sbuf provides a simple string buffer. One application where this comes
* in handy is the parsing of binary data: If there is an error in the parsing
* process due to invalid input data, printing an error message explaining what
* went wrong is definitely useful. However, just printing the actual error,
* without any information about the previous parsing steps, is usually not very
* helpful.
* Using sbuf, the parser can log the whole parsing process into a buffer using
* a printf like API. When an error ocurrs, all the information about previous
* parsing steps is there in the log, without any need for backtracking, and can
* be used to give a detailed and useful error description.
* When parsing completes successfully without any error, the log can just be
* discarded unless debugging is turned on, to not spam the log.
*
* For the described usecase, the code would look something like this:
*
* int sbuf_example(..., char **parser_log)
* {
* struct sbuf logbuf;
*
* sbuf_init(&logbuf, NULL, 0);
* sbuf_push(&logbuf, 0, "Starting parser\n");
*
* int rv = do_parse(&logbuf, ...);
*
* *parser_log = sbuf_buf(&logbuf);
*
* return 1;
* }
*
* In this case, sbuf_example uses a string buffer with undefined size, which will
* be allocated on the heap by sbuf. The caller of sbuf_example is expected to free
* the string returned in parser_log.
*/
struct sbuf {
bool fixed;
char *buf;
size_t size;
size_t pos;
int indent;
};
void sbuf_init(struct sbuf *dest, char *buf, size_t size);
void sbuf_reset(struct sbuf *buf);
const char *sbuf_buf(struct sbuf *buf);
void sbuf_free(struct sbuf *buf);
#include "lib/log.h"
void sbuf_push(struct sbuf *buf, int indent, const char *format, ...)
PRINTF_ATTRIBUTE(3, 4);
#endif

View File

@ -51,6 +51,7 @@ lib_libfrr_la_SOURCES = \
lib/ptm_lib.c \
lib/qobj.c \
lib/routemap.c \
lib/sbuf.c \
lib/sha256.c \
lib/sigevent.c \
lib/skiplist.c \
@ -125,6 +126,7 @@ pkginclude_HEADERS += \
lib/qobj.h \
lib/route_types.h \
lib/routemap.h \
lib/sbuf.h \
lib/sha256.h \
lib/sigevent.h \
lib/skiplist.h \

2
tests/.gitignore vendored
View File

@ -25,6 +25,8 @@ __pycache__
/bgpd/test_ecommunity
/bgpd/test_mp_attr
/bgpd/test_mpath
/isisd/test_fuzz_isis_tlv
/isisd/test_fuzz_isis_tlv_tests.h
/lib/cli/test_cli
/lib/cli/test_commands
/lib/cli/test_commands_defun.c

View File

@ -24,6 +24,13 @@ else
TESTS_BGPD =
endif
if ISISD
TESTS_ISISD = \
isisd/test_fuzz_isis_tlv
else
TESTS_ISISD =
endif
if OSPF6D
TESTS_OSPF6D = \
ospf6d/test_lsdb \
@ -61,6 +68,7 @@ check_PROGRAMS = \
lib/cli/test_cli \
lib/cli/test_commands \
$(TESTS_BGPD) \
$(TESTS_ISISD) \
$(TESTS_OSPF6D) \
# end
@ -75,7 +83,12 @@ lib/cli/test_commands_defun.c: ../vtysh/vtysh_cmd.c
< ../vtysh/vtysh_cmd.c \
> "$@"
BUILT_SOURCES = lib/cli/test_commands_defun.c
isisd/test_fuzz_isis_tlv_tests.h: $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
gzip -d < $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz > "$@"
BUILT_SOURCES = \
lib/cli/test_commands_defun.c \
isisd/test_fuzz_isis_tlv_tests.h
noinst_HEADERS = \
./helpers/c/prng.h \
@ -110,11 +123,14 @@ bgpd_test_capability_SOURCES = bgpd/test_capability.c
bgpd_test_ecommunity_SOURCES = bgpd/test_ecommunity.c
bgpd_test_mp_attr_SOURCES = bgpd/test_mp_attr.c
bgpd_test_mpath_SOURCES = bgpd/test_mpath.c
isisd_test_fuzz_isis_tlv_SOURCES = isisd/test_fuzz_isis_tlv.c
isisd_test_fuzz_isis_tlv_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_builddir)/tests/isisd
ospf6d_test_lsdb_SOURCES = ospf6d/test_lsdb.c lib/cli/common_cli.c
ALL_TESTS_LDADD = ../lib/libfrr.la @LIBCAP@
BGP_TEST_LDADD = ../bgpd/libbgp.a $(BGP_VNC_RFP_LIB) $(ALL_TESTS_LDADD) -lm
ISISD_TEST_LDADD = ../isisd/libisis.a $(ALL_TESTS_LDADD)
OSPF6_TEST_LDADD = ../ospf6d/libospf6.a $(ALL_TESTS_LDADD)
lib_test_buffer_LDADD = $(ALL_TESTS_LDADD)
@ -140,6 +156,7 @@ bgpd_test_capability_LDADD = $(BGP_TEST_LDADD)
bgpd_test_ecommunity_LDADD = $(BGP_TEST_LDADD)
bgpd_test_mp_attr_LDADD = $(BGP_TEST_LDADD)
bgpd_test_mpath_LDADD = $(BGP_TEST_LDADD)
isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD)
ospf6d_test_lsdb_LDADD = $(OSPF6_TEST_LDADD)
EXTRA_DIST = \
@ -151,6 +168,8 @@ EXTRA_DIST = \
bgpd/test_mpath.py \
helpers/python/frrsix.py \
helpers/python/frrtest.py \
isisd/test_fuzz_isis_tlv.py \
isisd/test_fuzz_isis_tlv_tests.h.gz \
lib/cli/test_commands.in \
lib/cli/test_commands.py \
lib/cli/test_commands.refout \

1
tests/isisd/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/*_afl/*

View File

@ -0,0 +1,188 @@
#include "test_fuzz_isis_tlv_tests.h"
#include <zebra.h>
#include "memory.h"
#include "sbuf.h"
#include "stream.h"
#include "thread.h"
#include "isisd/isis_circuit.h"
#include "isisd/isis_tlvs.h"
#define TEST_STREAM_SIZE 1500
struct thread_master *master;
int isis_sock_init(struct isis_circuit *circuit);
int isis_sock_init(struct isis_circuit *circuit)
{
return 0;
}
static bool atexit_registered;
static void show_meminfo_at_exit(void)
{
log_memstats_stderr("isis fuzztest");
}
static int comp_line(const void *p1, const void *p2)
{
return strcmp(*(char * const *)p1, *(char * const *)p2);
}
static char *sortlines(char *in)
{
size_t line_count = 1;
size_t rv_len = strlen(in) + 1;
size_t rv_pos = 0;
char *rv = XMALLOC(MTYPE_TMP, rv_len);
for (char *c = in; *c; c++) {
if (*c == '\n')
line_count++;
}
if (line_count == 1) {
strncpy(rv, in, rv_len);
return rv;
}
char **lines = XCALLOC(MTYPE_TMP, sizeof(char *)*line_count);
char *saveptr = NULL;
size_t i = 0;
for (char *line = strtok_r(in, "\n", &saveptr); line;
line = strtok_r(NULL, "\n", &saveptr)) {
lines[i++] = line;
assert(i <= line_count);
}
line_count = i;
qsort(lines, line_count, sizeof(char *), comp_line);
for (i = 0; i < line_count; i++) {
int printf_rv = snprintf(rv + rv_pos, rv_len - rv_pos, "%s\n", lines[i]);
assert(printf_rv >= 0);
rv_pos += printf_rv;
}
XFREE(MTYPE_TMP, lines);
return rv;
}
static int test(FILE *input, FILE *output)
{
struct stream *s = stream_new(TEST_STREAM_SIZE);
char buf[TEST_STREAM_SIZE];
size_t bytes_read = 0;
if (!atexit_registered) {
atexit(show_meminfo_at_exit);
atexit_registered = true;
}
while (STREAM_WRITEABLE(s) && !feof(input)) {
bytes_read = fread(buf, 1, STREAM_WRITEABLE(s), input);
if (bytes_read == 0)
break;
stream_put(s, buf, bytes_read);
}
if (bytes_read && !feof(input)) {
fprintf(output, "Too much input data.\n");
stream_free(s);
return 1;
}
stream_set_getp(s, 0);
struct isis_tlvs *tlvs;
const char *log;
int rv = isis_unpack_tlvs(STREAM_READABLE(s), s, &tlvs, &log);
if (rv) {
fprintf(output, "Could not unpack TLVs:\n%s\n", log);
isis_free_tlvs(tlvs);
stream_free(s);
return 2;
}
fprintf(output, "Unpack log:\n%s", log);
const char *s_tlvs = isis_format_tlvs(tlvs);
fprintf(output, "Unpacked TLVs:\n%s", s_tlvs);
struct isis_tlvs *tlv_copy = isis_copy_tlvs(tlvs);
isis_free_tlvs(tlvs);
struct stream *s2 = stream_new(TEST_STREAM_SIZE);
if (isis_pack_tlvs(tlv_copy, s2, (size_t)-1, false, false)) {
fprintf(output, "Could not pack TLVs.\n");
assert(0);
}
stream_set_getp(s2, 0);
rv = isis_unpack_tlvs(STREAM_READABLE(s2), s2, &tlvs, &log);
if (rv) {
fprintf(output, "Could not unpack own TLVs:\n%s\n", log);
assert(0);
}
char *orig_tlvs = XSTRDUP(MTYPE_TMP, s_tlvs);
s_tlvs = isis_format_tlvs(tlvs);
if (strcmp(orig_tlvs, s_tlvs)) {
fprintf(output,
"Deserialized and Serialized LSP seem to differ.\n");
fprintf(output, "Re-Unpacked TLVs:\n%s", s_tlvs);
assert(0);
}
isis_free_tlvs(tlv_copy);
stream_free(s);
stream_free(s2);
struct list *fragments = isis_fragment_tlvs(tlvs, 550);
isis_free_tlvs(tlvs);
if (!fragments) {
XFREE(MTYPE_TMP, orig_tlvs);
return 0;
}
s = stream_new(550);
struct sbuf fragment_format;
sbuf_init(&fragment_format, NULL, 0);
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(fragments, node, tlvs)) {
stream_reset(s);
int rv = isis_pack_tlvs(tlvs, s, (size_t)-1, false, false);
if (rv) {
fprintf(output, "Could not pack fragment, too large.\n");
assert(0);
}
sbuf_push(&fragment_format, 0, "%s", isis_format_tlvs(tlvs));
isis_free_tlvs(tlvs);
}
list_delete(fragments);
stream_free(s);
char *fragment_content = sortlines((char *)sbuf_buf(&fragment_format));
sbuf_free(&fragment_format);
char *orig_tlv_content = sortlines(orig_tlvs);
XFREE(MTYPE_TMP, orig_tlvs);
if (strcmp(fragment_content, orig_tlv_content)) {
fprintf(output, "Fragmented and unfragmented LSP seem to differ.\n");
fprintf(output, "Original:\n%s\nFragmented:\n%s\n",
orig_tlv_content, fragment_content);
assert(0);
}
XFREE(MTYPE_TMP, fragment_content);
XFREE(MTYPE_TMP, orig_tlv_content);
return 0;
}

View File

@ -0,0 +1,6 @@
import frrtest
class TestFuzzIsisTLV(frrtest.TestMultiOut):
program = './test_fuzz_isis_tlv'
TestFuzzIsisTLV.exit_cleanly()

Binary file not shown.