0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-03-14 02:17:04 +00:00

OSPF: Statistics

Count packet rx/tx and error conditions, per iface and globally.
Show them in 'show ospf' / 'show ospf interface'.

Also removee one level of indentation for areas in 'show ospf' command.
This commit is contained in:
Ondrej Zajicek (work) 2018-10-24 16:15:28 +02:00
parent 4d3d34f599
commit 60dda81b82
10 changed files with 149 additions and 65 deletions

View File

@ -218,11 +218,15 @@ ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
void
ospf_rxmt_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
{
struct ospf_iface *ifa = n->ifa;
ASSERT(n->state > NEIGHBOR_EXSTART);
if (!n->ldd_buffer)
{
log(L_WARN "%s: No DBDES packet for retransmit", p->p.name);
STATS(bad_dbdes);
ospf_neigh_sm(n, INM_SEQMIS);
return;
}
@ -251,18 +255,18 @@ ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_ne
/* RFC 2328 10.6 and RFC 5340 4.2.2 */
if (!lsa_type)
DROP1("LSA of unknown type");
DROP1(bad_dbdes, "LSA of unknown type");
if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS))
DROP1("LSA with AS scope in stub area");
DROP1(bad_dbdes, "LSA with AS scope in stub area");
/* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */
if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT))
DROP1("rt-summary-LSA in stub area");
DROP1(bad_dbdes, "rt-summary-LSA in stub area");
/* Not explicitly mentioned in RFC 5340 4.2.2 but makes sense */
if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
DROP1("LSA with invalid scope");
DROP1(bad_dbdes, "LSA with invalid scope");
en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER))
@ -311,6 +315,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
if (plen < ospf_dbdes_hdrlen(p))
{
LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen);
STATS2(bad_pkt, dropped);
return;
}
@ -397,13 +402,13 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
goto duplicate;
if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS))
DROP("MS-bit mismatch", rcv_imms);
DROP(bad_dbdes, "MS-bit mismatch", rcv_imms);
if (rcv_imms & DBDES_I)
DROP("I-bit mismatch", rcv_imms);
DROP(bad_dbdes, "I-bit mismatch", rcv_imms);
if (rcv_options != n->options)
DROP("options mismatch", rcv_options);
DROP(bad_dbdes, "options mismatch", rcv_options);
n->ddr = rcv_ddseq;
n->imms = rcv_imms;
@ -413,7 +418,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
/* MASTER */
if (rcv_ddseq != n->dds)
DROP("DD sequence number mismatch", rcv_ddseq);
DROP(bad_dbdes, "DD sequence number mismatch", rcv_ddseq);
n->dds++;
@ -435,7 +440,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
/* SLAVE */
if (rcv_ddseq != (n->dds + 1))
DROP("DD sequence number mismatch", rcv_ddseq);
DROP(bad_dbdes, "DD sequence number mismatch", rcv_ddseq);
n->ddr = rcv_ddseq;
n->dds = rcv_ddseq;
@ -457,7 +462,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
(rcv_ddseq == n->ddr))
goto duplicate;
DROP("too late for DD exchange", n->state);
DROP(bad_dbdes, "too late for DD exchange", n->state);
default:
bug("Undefined interface state");

View File

@ -206,7 +206,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_hello2_packet *ps = (void *) pkt;
if (plen < sizeof(struct ospf_hello2_packet))
DROP("too short", plen);
DROP(bad_pkt, "too short", plen);
rcv_iface_id = 0;
rcv_helloint = ntohs(ps->helloint);
@ -218,12 +218,12 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
int pxlen = u32_masklen(ntohl(ps->netmask));
if (pxlen < 0)
DROP("prefix garbled", ntohl(ps->netmask));
DROP(bad_pkt, "prefix garbled", ntohl(ps->netmask));
if ((ifa->type != OSPF_IT_VLINK) &&
(ifa->type != OSPF_IT_PTP) &&
((uint) pxlen != ifa->addr->prefix.pxlen))
DROP("prefix length mismatch", pxlen);
DROP(bad_hello, "prefix length mismatch", pxlen);
neighbors = ps->neighbors;
neigh_count = (plen - sizeof(struct ospf_hello2_packet)) / sizeof(u32);
@ -233,7 +233,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_hello3_packet *ps = (void *) pkt;
if (plen < sizeof(struct ospf_hello3_packet))
DROP("too short", plen);
DROP(bad_pkt, "too short", plen);
rcv_iface_id = ntohl(ps->iface_id);
rcv_helloint = ntohs(ps->helloint);
@ -248,18 +248,18 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
}
if (rcv_helloint != ifa->helloint)
DROP("hello interval mismatch", rcv_helloint);
DROP(bad_hello, "hello interval mismatch", rcv_helloint);
if (rcv_deadint != ifa->deadint)
DROP("dead interval mismatch", rcv_deadint);
DROP(bad_hello, "dead interval mismatch", rcv_deadint);
/* Check whether bits E, N match */
if ((rcv_options ^ loc_options) & (OPT_E | OPT_N))
DROP("area type mismatch", rcv_options);
DROP(bad_hello, "area type mismatch", rcv_options);
/* RFC 5838 2.4 - AF-bit check unless on IPv6 unicast */
if ((loc_options & OPT_AF) && !(loc_options & OPT_V6) && !(rcv_options & OPT_AF))
DROP("AF-bit mismatch", rcv_options);
DROP(bad_hello, "AF-bit mismatch", rcv_options);
/* Check consistency of existing neighbor entry */
if (n)
@ -295,12 +295,12 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct nbma_node *nn = find_nbma_node(ifa, faddr);
if (!nn && ifa->strictnbma)
DROP1("new neighbor denied");
DROP1(bad_hello, "new neighbor denied");
if (nn && (ifa->type == OSPF_IT_NBMA) &&
(((rcv_priority == 0) && nn->eligible) ||
((rcv_priority > 0) && !nn->eligible)))
DROP("eligibility mismatch", rcv_priority);
DROP(bad_hello, "eligibility mismatch", rcv_priority);
if (nn)
nn->found = 1;

View File

@ -1327,6 +1327,23 @@ ospf_if_notify(struct proto *P, uint flags, struct iface *iface)
iface_list even when down */
}
void
ospf_iface_stats(int c, struct ospf_iface_stats *s)
{
cli_msg(c, "\trx-hello %u rx-dbdes %u rx-lsreq %u rx-lsupd %u rx-lsack %u rx-vlink %u",
s->rx_pkts[0], s->rx_pkts[1], s->rx_pkts[2], s->rx_pkts[3], s->rx_pkts[4], s->rx_vlink);
cli_msg(c, "\ttx-hello %u tx-dbdes %u tx-lsreq %u tx-lsupd %u tx-lsack %u tx-vlink %u",
s->tx_pkts[0], s->tx_pkts[1], s->tx_pkts[2], s->tx_pkts[3], s->tx_pkts[4], s->tx_vlink);
cli_msg(c, "\tdropped %u bad-pkt %u bad-ver %u bad-au-type %u bad-auth %u bad-chksum %u",
s->dropped, s->bad_pkt, s->bad_ver, s->bad_au_type, s->bad_auth, s->bad_check);
cli_msg(c, "\tbad-ttl %u bad-src %u bad-area %u bad-nbr %u bad-pkt-type %u bad-state %u",
s->bad_ttl, s->bad_src, s->bad_area, s->bad_nbr, s->bad_pkt_type, s->bad_state);
cli_msg(c, "\tbad-hello %u bad-dbdes %u bad-lsreq %u bad-lsupd %u bad-lsack %u bad-lsa %u",
s->bad_hello, s->bad_dbdes, s->bad_lsreq, s->bad_lsupd, s->bad_lsack, s->bad_lsa);
cli_msg(c, "\tsk-error %u tx-queue-full %u tx-no-key %u",
s->sk_error, s->tx_queue_full, s->tx_no_key);
}
void
ospf_iface_info(struct ospf_iface *ifa)
{
@ -1379,4 +1396,7 @@ ospf_iface_info(struct ospf_iface *ifa)
cli_msg(-1015, "\tBackup designated router (ID): %R", ifa->bdrid);
cli_msg(-1015, "\tBackup designated router (IP): %I", ifa->bdrip);
}
cli_msg(-1015, "\tStatistics:");
ospf_iface_stats(-1015, &ifa->stats);
}

View File

@ -133,7 +133,7 @@ ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_proto *p = ifa->oa->po;
struct ospf_lsa_header lsa, *lsas;
struct top_hash_entry *ret, *en;
uint i, lsa_count;
uint i, lsa_count, bad = 0;
u32 lsa_type, lsa_domain;
/* RFC 2328 13.7 */
@ -145,6 +145,7 @@ ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa,
if (n->state < NEIGHBOR_EXCHANGE)
{
OSPF_TRACE(D_PACKETS, "LSACK packet ignored - lesser state than Exchange");
STATS2(bad_state, dropped);
return;
}
@ -169,6 +170,10 @@ ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa,
ret->lsa.sn, ret->lsa.age, ret->lsa.checksum);
OSPF_TRACE(D_PACKETS, " It has: Seq: %08x, Age: %4u, Sum: %04x",
lsa.sn, lsa.age, lsa.checksum);
if (!bad++)
STATS(bad_lsack);
continue;
}

View File

@ -110,6 +110,7 @@ ospf_receive_lsreq(struct ospf_packet *pkt, struct ospf_iface *ifa,
if (n->state < NEIGHBOR_EXCHANGE)
{
OSPF_TRACE(D_PACKETS, "LSREQ packet ignored - lesser state than Exchange");
STATS2(bad_state, dropped);
return;
}
@ -134,6 +135,7 @@ ospf_receive_lsreq(struct ospf_packet *pkt, struct ospf_iface *ifa,
{
LOG_LSA1("Bad LSR (Type: %04x, Id: %R, Rt: %R) in LSREQ", type, id, rt);
LOG_LSA2(" received from nbr %R on %s - LSA is missing", n->rid, ifa->ifname);
STATS2(bad_lsreq, dropped);
ospf_neigh_sm(n, INM_BADLSREQ);
return;

View File

@ -487,6 +487,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
if (plen < ospf_lsupd_hdrlen(p))
{
LOG_PKT("Bad LSUPD packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen);
STATS2(bad_pkt, dropped);
return;
}
@ -495,6 +496,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
if (n->state < NEIGHBOR_EXCHANGE)
{
OSPF_TRACE(D_PACKETS, "LSUPD packet ignored - lesser state than Exchange");
STATS2(bad_state, dropped);
return;
}
@ -510,7 +512,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
u32 lsa_len, lsa_type, lsa_domain;
if ((offset + sizeof(struct ospf_lsa_header)) > plen)
DROP("too short", plen);
DROP(bad_pkt, "too short", plen);
/* LSA header in network order */
lsa_n = ((void *) pkt) + offset;
@ -518,10 +520,10 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
offset += lsa_len;
if (offset > plen)
DROP("too short", plen);
DROP(bad_pkt, "too short", plen);
if (((lsa_len % 4) != 0) || (lsa_len <= sizeof(struct ospf_lsa_header)))
DROP("invalid LSA length", lsa_len);
DROP(bad_pkt, "invalid LSA length", lsa_len);
/* LSA header in host order */
lsa_ntoh_hdr(lsa_n, &lsa);
@ -643,7 +645,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
/* 13. (6) - received LSA is in Link state request list (but not newer) */
if (ospf_hash_find_entry(n->lsrqh, en) != NULL)
DROP1("error in LSA database exchange");
DROP1(bad_lsupd, "error in LSA database exchange");
/* 13. (7) - received LSA is same */
if (lsa_comp(&lsa, &en->lsa) == CMP_SAME)
@ -679,6 +681,7 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
skip:
LOG_LSA1("Bad LSA (Type: %04x, Id: %R, Rt: %R) in LSUPD", lsa_type, lsa.id, lsa.rt);
LOG_LSA2(" received from nbr %R on %s - %s", n->rid, ifa->ifname, err_dsc);
STATS(bad_lsa);
}
/* Send direct LSACKs */

View File

@ -256,6 +256,9 @@ ospf_start(struct proto *P)
p->gr = ospf_top_new(p, P->pool);
s_init_list(&(p->lsal));
memset(&(p->iface_stats), 0, sizeof(struct ospf_iface_stats));
p->spf_count = 0;
p->flood_event = ev_new(P->pool);
p->flood_event->hook = ospf_flood_event;
p->flood_event->data = p;
@ -772,11 +775,15 @@ ospf_sh(struct proto *P)
cli_msg(-1014, "Stub router: %s", (p->stub_router ? "Yes" : "No"));
cli_msg(-1014, "RT scheduler tick: %d", p->tick);
cli_msg(-1014, "Number of areas: %u", p->areano);
cli_msg(-1014, "Number of LSAs in DB:\t%u", p->gr->hash_entries);
cli_msg(-1014, "Number of LSAs in DB: %u", p->gr->hash_entries);
cli_msg(-1014, "Number of SPF runs: %u", p->spf_count);
cli_msg(-1014, "Statistics:");
ospf_iface_stats(-1014, &p->iface_stats);
WALK_LIST(oa, p->area_list)
{
cli_msg(-1014, "\tArea: %R (%u) %s", oa->areaid, oa->areaid,
cli_msg(-1014, "Area: %R (%u) %s", oa->areaid, oa->areaid,
oa->areaid == 0 ? "[BACKBONE]" : "");
ifano = 0;
nno = 0;
@ -795,26 +802,26 @@ ospf_sh(struct proto *P)
}
}
cli_msg(-1014, "\t\tStub:\t%s", oa_is_stub(oa) ? "Yes" : "No");
cli_msg(-1014, "\t\tNSSA:\t%s", oa_is_nssa(oa) ? "Yes" : "No");
cli_msg(-1014, "\t\tTransit:\t%s", oa->trcap ? "Yes" : "No");
cli_msg(-1014, "\tStub:\t%s", oa_is_stub(oa) ? "Yes" : "No");
cli_msg(-1014, "\tNSSA:\t%s", oa_is_nssa(oa) ? "Yes" : "No");
cli_msg(-1014, "\tTransit:\t%s", oa->trcap ? "Yes" : "No");
if (oa_is_nssa(oa))
cli_msg(-1014, "\t\tNSSA translation:\t%s%s", oa->translate ? "Yes" : "No",
cli_msg(-1014, "\tNSSA translation:\t%s%s", oa->translate ? "Yes" : "No",
oa->translate == TRANS_WAIT ? " (run down)" : "");
cli_msg(-1014, "\t\tNumber of interfaces:\t%u", ifano);
cli_msg(-1014, "\t\tNumber of neighbors:\t%u", nno);
cli_msg(-1014, "\t\tNumber of adjacent neighbors:\t%u", adjno);
cli_msg(-1014, "\tNumber of interfaces:\t%u", ifano);
cli_msg(-1014, "\tNumber of neighbors:\t%u", nno);
cli_msg(-1014, "\tNumber of adjacent neighbors:\t%u", adjno);
firstfib = 1;
FIB_WALK(&oa->net_fib, struct area_net, anet)
{
if(firstfib)
{
cli_msg(-1014, "\t\tArea networks:");
cli_msg(-1014, "\tArea networks:");
firstfib = 0;
}
cli_msg(-1014, "\t\t\t%1N\t%s\t%s", anet->fn.addr,
cli_msg(-1014, "\t\t%1N\t%s\t%s", anet->fn.addr,
anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
}
FIB_WALK_END;
@ -824,10 +831,10 @@ ospf_sh(struct proto *P)
{
if(firstfib)
{
cli_msg(-1014, "\t\tArea external networks:");
cli_msg(-1014, "\tArea external networks:");
firstfib = 0;
}
cli_msg(-1014, "\t\t\t%1N\t%s\t%s", anet->fn.addr,
cli_msg(-1014, "\t\t%1N\t%s\t%s", anet->fn.addr,
anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
}
FIB_WALK_END;

View File

@ -69,6 +69,8 @@
#define MINLSARRIVAL (1 S_)
#define LSINFINITY 0xffffff
#define OSPF_PKT_TYPES 5 /* HELLO_P .. LSACK_P */
#define OSPF_DEFAULT_TICK 1
#define OSPF_DEFAULT_STUB_COST 1000
#define OSPF_DEFAULT_ECMP_LIMIT 16
@ -197,6 +199,14 @@ struct ospf_iface_patt
#define WAIT_DMH 4
/* Value of Wait timer - not found it in RFC * - using 4*HELLO */
struct ospf_iface_stats
{
uint rx_pkts[OSPF_PKT_TYPES], tx_pkts[OSPF_PKT_TYPES], rx_vlink, tx_vlink;
uint dropped, bad_pkt, bad_ver, bad_au_type, bad_auth, bad_check;
uint bad_ttl, bad_src, bad_area, bad_rid, bad_nbr, bad_pkt_type;
uint bad_hello, bad_dbdes, bad_lsreq, bad_lsupd, bad_lsack, bad_state;
uint bad_lsa, sk_error, tx_queue_full, tx_no_key;
};
struct ospf_proto
@ -230,6 +240,8 @@ struct ospf_proto
sock *vlink_sk; /* IP socket used for vlink TX */
u32 router_id;
u32 last_vlink_id; /* Interface IDs for vlinks (starts at 0x80000000) */
struct ospf_iface_stats iface_stats;
uint spf_count; /* Number of SPF calculations */
struct tbf log_pkt_tbf; /* TBF for packet messages */
struct tbf log_lsa_tbf; /* TBF for LSA messages */
};
@ -311,6 +323,7 @@ struct ospf_iface
struct top_hash_entry *net_lsa; /* Originated network LSA */
struct top_hash_entry *pxn_lsa; /* Originated prefix LSA */
struct top_hash_entry **flood_queue; /* LSAs queued for LSUPD */
struct ospf_iface_stats stats; /* Packet statistics */
u8 update_link_lsa;
u8 update_net_lsa;
u16 flood_queue_used; /* The current number of LSAs in flood_queue */
@ -903,6 +916,7 @@ struct ospf_iface *ospf_iface_find(struct ospf_proto *p, struct iface *what);
void ospf_if_notify(struct proto *P, uint flags, struct iface *iface);
void ospf_ifa_notify2(struct proto *P, uint flags, struct ifa *a);
void ospf_ifa_notify3(struct proto *P, uint flags, struct ifa *a);
void ospf_iface_stats(int c, struct ospf_iface_stats *s);
void ospf_iface_info(struct ospf_iface *ifa);
void ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip);
void ospf_iface_new_vlink(struct ospf_proto *p, struct ospf_iface_patt *ip);
@ -951,8 +965,10 @@ static inline void ospf_send_to_des(struct ospf_iface *ifa)
}
#ifndef PARSER
#define DROP(DSC,VAL) do { err_dsc = DSC; err_val = VAL; goto drop; } while(0)
#define DROP1(DSC) do { err_dsc = DSC; goto drop; } while(0)
#define STATS(KEY) do { ifa->stats.KEY++; p->iface_stats.KEY++; } while(0)
#define STATS2(KEY1, KEY2) do { STATS(KEY1); STATS(KEY2); } while(0)
#define DROP(KEY,DSC,VAL) do { STATS(KEY); STATS(dropped); err_dsc = DSC; err_val = VAL; goto drop; } while(0)
#define DROP1(KEY,DSC) do { STATS(KEY); STATS(dropped); err_dsc = DSC; goto drop; } while(0)
#define SKIP(DSC) do { err_dsc = DSC; goto skip; } while(0)
#endif

View File

@ -36,6 +36,7 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
static void
ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen)
{
struct ospf_proto *p = ifa->oa->po;
struct password_item *pass = NULL;
union ospf_auth *auth = (void *) (pkt + 1);
@ -52,7 +53,8 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen)
pass = password_find(ifa->passwords, 1);
if (!pass)
{
log(L_ERR "No suitable password found for authentication");
log(L_ERR "%s: No suitable password found for authentication", p->p.name);
STATS(tx_no_key);
return;
}
strncpy(auth->password, pass->password, sizeof(auth->password));
@ -69,7 +71,8 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt, uint *plen)
pass = password_find(ifa->passwords, 0);
if (!pass)
{
log(L_ERR "No suitable password found for authentication");
log(L_ERR "%s: No suitable password found for authentication", p->p.name);
STATS(tx_no_key);
return;
}
@ -129,7 +132,7 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
u8 autype = pkt->autype;
if (autype != ifa->autype)
DROP("authentication method mismatch", autype);
DROP(bad_au_type, "authentication method mismatch", autype);
switch (autype)
{
@ -139,25 +142,25 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
case OSPF_AUTH_SIMPLE:
pass = password_find(ifa->passwords, 1);
if (!pass)
DROP1("no password found");
DROP1(bad_auth, "no password found");
if (!password_verify(pass, auth->password, sizeof(auth->password)))
DROP("wrong password", pass->id);
DROP(bad_auth, "wrong password", pass->id);
return 1;
case OSPF_AUTH_CRYPT:
pass = password_find_by_id(ifa->passwords, auth->c32.keyid);
if (!pass)
DROP("no suitable password found", auth->c32.keyid);
DROP(bad_auth, "no suitable password found", auth->c32.keyid);
uint auth_len = mac_type_length(pass->alg);
if (plen + auth->c32.len > len)
DROP("packet length mismatch", len);
DROP(bad_pkt, "packet length mismatch", len);
if (auth->c32.len != auth_len)
DROP("wrong authentication length", auth->c32.len);
DROP(bad_auth, "wrong authentication length", auth->c32.len);
u32 rcv_csn = ntohl(auth->c32.csn);
if (n && (rcv_csn < n->csn))
@ -167,6 +170,7 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
LOG_PKT_AUTH("Authentication failed for nbr %R on %s - "
"lower sequence number (rcv %u, old %u)",
n->rid, ifa->ifname, rcv_csn, n->csn);
STATS2(bad_auth, dropped);
return 0;
}
@ -182,7 +186,7 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
if (!mac_verify(pass->alg, pass->password, pass->length,
(byte *) pkt, plen + auth_len, auth_data))
DROP("wrong authentication code", pass->id);
DROP(bad_auth, "wrong authentication code", pass->id);
if (n)
n->csn = rcv_csn;
@ -268,17 +272,17 @@ ospf_rx_hook(sock *sk, uint len)
if (pkt == NULL)
DROP("bad IP header", len);
DROP(bad_pkt, "bad IP header", len);
if (len < sizeof(struct ospf_packet))
DROP("too short", len);
DROP(bad_pkt, "too short", len);
if (pkt->version != ospf_get_version(p))
DROP("version mismatch", pkt->version);
DROP(bad_ver, "version mismatch", pkt->version);
uint plen = ntohs(pkt->length);
if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0))
DROP("invalid length", plen);
DROP(bad_pkt, "invalid length", plen);
if (sk->flags & SKF_TRUNCATED)
{
@ -290,11 +294,11 @@ ospf_rx_hook(sock *sk, uint len)
if (!ifa->cf->rx_buffer && (bs > sk->rbsize))
sk_set_rbsize(sk, bs);
DROP("truncated", plen);
DROP(sk_error, "truncated", plen);
}
if (plen > len)
DROP("length mismatch", plen);
DROP(bad_pkt, "length mismatch", plen);
if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT))
{
@ -303,7 +307,7 @@ ospf_rx_hook(sock *sk, uint len)
void *body = ((void *) pkt) + hlen;
if (!ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL))
DROP1("invalid checksum");
DROP1(bad_check, "invalid checksum");
}
/* Third, we resolve associated iface and handle vlinks. */
@ -321,7 +325,7 @@ ospf_rx_hook(sock *sk, uint len)
/* It is real iface, source should be local (in OSPFv2) */
if (ospf_is_v2(p) && !src_local)
DROP1("strange source address");
DROP1(bad_src, "strange source address");
goto found;
}
@ -365,7 +369,7 @@ ospf_rx_hook(sock *sk, uint len)
if (instance_id != ifa->instance_id)
return 1;
DROP("area mismatch", areaid);
DROP(bad_area, "area mismatch", areaid);
}
@ -378,13 +382,13 @@ found:
/* TTL check must be done after instance dispatch */
if (ifa->check_ttl && (sk->rcv_ttl < 255))
DROP("wrong TTL", sk->rcv_ttl);
DROP(bad_ttl, "wrong TTL", sk->rcv_ttl);
if (rid == p->router_id)
DROP1("my own router ID");
DROP1(bad_nbr, "my own router ID");
if (rid == 0)
DROP1("zero router ID");
DROP1(bad_nbr, "zero router ID");
/* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */
uint t = ifa->type;
@ -398,13 +402,23 @@ found:
{
OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown nbr %R on %s, src %I",
rid, ifa->ifname, sk->faddr);
STATS2(bad_nbr, dropped);
return 1;
}
/* Check packet type here, ospf_pkt_checkauth3() expects valid values */
if (pkt->type < HELLO_P || pkt->type > LSACK_P)
DROP(bad_pkt_type, "invalid packet type", pkt->type);
/* ospf_pkt_checkauth() has its own error logging */
if (ospf_is_v2(p) && !ospf_pkt_checkauth(n, ifa, pkt, len))
return 1;
STATS(rx_pkts[pkt->type - 1]);
if (ifa->type == OSPF_IT_VLINK)
STATS(rx_vlink);
switch (pkt->type)
{
case HELLO_P:
@ -426,9 +440,6 @@ found:
case LSACK_P:
ospf_receive_lsack(pkt, ifa, n);
break;
default:
DROP("invalid packet type", pkt->type);
};
return 1;
@ -455,6 +466,7 @@ ospf_err_hook(sock * sk, int err)
struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
struct ospf_proto *p = ifa->oa->po;
log(L_ERR "%s: Socket error on %s: %M", p->p.name, ifa->ifname, err);
STATS(sk_error);
}
void
@ -462,6 +474,9 @@ ospf_verr_hook(sock *sk, int err)
{
struct ospf_proto *p = (struct ospf_proto *) (sk->data);
log(L_ERR "%s: Vlink socket error: %M", p->p.name, err);
/* Cannot use STATS() as there is no specific iface */
p->iface_stats.sk_error++;
}
void
@ -469,6 +484,7 @@ ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
{
sock *sk = ifa->sk;
struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
struct ospf_proto *p = ifa->oa->po;
uint plen = ntohs(pkt->length);
if (ospf_is_v2(ifa->oa->po))
@ -476,7 +492,16 @@ ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
int done = sk_send_to(sk, plen, dst, 0);
if (!done)
log(L_WARN "OSPF: TX queue full on %s", ifa->ifname);
{
log(L_WARN "%s: TX queue full on %s", p->p.name, ifa->ifname);
STATS(tx_queue_full);
return;
}
STATS(tx_pkts[pkt->type - 1]);
if (ifa->type == OSPF_IT_VLINK)
STATS(tx_vlink);
}
void

View File

@ -1649,6 +1649,7 @@ ospf_rt_spf(struct ospf_proto *p)
return;
OSPF_TRACE(D_EVENTS, "Starting routing table calculation");
p->spf_count++;
/* 16. (1) */
ospf_rt_reset(p);