Merge branch 'master' of ssh://git.nic.cz/projects/bird/GIT/bird
This commit is contained in:
commit
96599c957b
16 changed files with 917 additions and 622 deletions
|
@ -490,13 +490,18 @@ This argument can be omitted if there exists only a single instance.
|
||||||
<tag>show ospf neighbors [<m/name/] ["<m/interface/"]</tag>
|
<tag>show ospf neighbors [<m/name/] ["<m/interface/"]</tag>
|
||||||
Show a list of OSPF neighbors and a state of adjacency to them.
|
Show a list of OSPF neighbors and a state of adjacency to them.
|
||||||
|
|
||||||
<tag>show ospf state [<m/name/]</tag>
|
<tag>show ospf state [all] [<m/name/]</tag>
|
||||||
Show detailed information about OSPF areas based on a content of link-state database.
|
Show detailed information about OSPF areas based on a content
|
||||||
It shows network topology, aggregated networks and routers from other areas and external routes.
|
of the link-state database. It shows network topology, stub
|
||||||
|
networks, aggregated networks and routers from other areas and
|
||||||
|
external routes. The command shows information about reachable
|
||||||
|
network nodes, use option <cf/all/ to show information about
|
||||||
|
all network nodes in the link-state database.
|
||||||
|
|
||||||
<tag>show ospf topology [<m/name/]</tag>
|
<tag>show ospf topology [all] [<m/name/]</tag>
|
||||||
Show a topology of OSPF areas based on a content of link-state database.
|
Show a topology of OSPF areas based on a content of the
|
||||||
It is just a stripped-down version of 'show ospf state'.
|
link-state database. It is just a stripped-down version of
|
||||||
|
'show ospf state'.
|
||||||
|
|
||||||
<tag>show static [<m/name/]</tag>
|
<tag>show static [<m/name/]</tag>
|
||||||
Show detailed information about static routes.
|
Show detailed information about static routes.
|
||||||
|
|
|
@ -15,26 +15,21 @@
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
#include "checksum.h"
|
#include "checksum.h"
|
||||||
|
|
||||||
static u16 /* One-complement addition */
|
static inline u32
|
||||||
add16(u16 sum, u16 x)
|
|
||||||
{
|
|
||||||
u16 z = sum + x;
|
|
||||||
return z + (z < sum);
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32
|
|
||||||
add32(u32 sum, u32 x)
|
add32(u32 sum, u32 x)
|
||||||
{
|
{
|
||||||
u32 z = sum + x;
|
u32 z = sum + x;
|
||||||
return z + (z < sum);
|
// return z + (z < sum);
|
||||||
|
|
||||||
|
/* add carry */
|
||||||
|
if (z < x)
|
||||||
|
z++;
|
||||||
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16
|
static u16
|
||||||
ipsum_calc_block(u16 *x, unsigned len, u16 sum)
|
ipsum_calc_block(u32 *buf, unsigned len, u16 isum)
|
||||||
{
|
{
|
||||||
int rest;
|
|
||||||
u32 tmp, *xx;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A few simple facts about the IP checksum (see RFC 1071 for detailed
|
* A few simple facts about the IP checksum (see RFC 1071 for detailed
|
||||||
* discussion):
|
* discussion):
|
||||||
|
@ -47,27 +42,17 @@ ipsum_calc_block(u16 *x, unsigned len, u16 sum)
|
||||||
* usual alignment requirements and is reasonably fast.
|
* usual alignment requirements and is reasonably fast.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ASSERT(!(len % 2));
|
ASSERT(!(len % 4));
|
||||||
if (!len)
|
if (!len)
|
||||||
return sum;
|
return isum;
|
||||||
len >>= 1;
|
|
||||||
if ((unsigned long) x & 2) /* Align to 32-bit boundary */
|
u32 *end = buf + (len >> 2);
|
||||||
{
|
u32 sum = isum;
|
||||||
sum = add16(sum, *x++);
|
while (buf < end)
|
||||||
len--;
|
sum = add32(sum, *buf++);
|
||||||
}
|
|
||||||
rest = len & 1;
|
sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */
|
||||||
len >>= 1;
|
sum += (sum >> 16); /* add carry */
|
||||||
tmp = 0;
|
|
||||||
xx = (u32 *) x;
|
|
||||||
while (len)
|
|
||||||
{
|
|
||||||
tmp = add32(tmp, *xx++);
|
|
||||||
len--;
|
|
||||||
}
|
|
||||||
sum = add16(sum, add16(tmp & 0xffff, tmp >> 16U));
|
|
||||||
if (rest)
|
|
||||||
sum = add16(sum, *(u16 *) xx);
|
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,6 @@ ospf_vlink_start: VIRTUAL LINK idval
|
||||||
add_tail(&this_area->vlink_list, NODE this_ipatt);
|
add_tail(&this_area->vlink_list, NODE this_ipatt);
|
||||||
init_list(&this_ipatt->ipn_list);
|
init_list(&this_ipatt->ipn_list);
|
||||||
OSPF_PATT->vid = $3;
|
OSPF_PATT->vid = $3;
|
||||||
OSPF_PATT->cost = COST_D;
|
|
||||||
OSPF_PATT->helloint = HELLOINT_D;
|
OSPF_PATT->helloint = HELLOINT_D;
|
||||||
OSPF_PATT->rxmtint = RXMTINT_D;
|
OSPF_PATT->rxmtint = RXMTINT_D;
|
||||||
OSPF_PATT->inftransdelay = INFTRANSDELAY_D;
|
OSPF_PATT->inftransdelay = INFTRANSDELAY_D;
|
||||||
|
@ -315,11 +314,21 @@ CF_CLI(SHOW OSPF NEIGHBORS, optsym opttext, [<name>] [\"<interface>\"], [[Show i
|
||||||
CF_CLI(SHOW OSPF INTERFACE, optsym opttext, [<name>] [\"<interface>\"], [[Show information about interface]])
|
CF_CLI(SHOW OSPF INTERFACE, optsym opttext, [<name>] [\"<interface>\"], [[Show information about interface]])
|
||||||
{ ospf_sh_iface(proto_get_named($4, &proto_ospf), $5); };
|
{ ospf_sh_iface(proto_get_named($4, &proto_ospf), $5); };
|
||||||
|
|
||||||
CF_CLI(SHOW OSPF TOPOLOGY, optsym opttext, [<name>], [[Show information about OSPF network topology]])
|
CF_CLI_HELP(SHOW OSPF TOPOLOGY, [all] [<name>], [[Show information about OSPF network topology]])
|
||||||
{ ospf_sh_state(proto_get_named($4, &proto_ospf), 0); };
|
|
||||||
|
|
||||||
CF_CLI(SHOW OSPF STATE, optsym opttext, [<name>], [[Show information about OSPF network state]])
|
CF_CLI(SHOW OSPF TOPOLOGY, optsym opttext, [<name>], [[Show information about reachable OSPF network topology]])
|
||||||
{ ospf_sh_state(proto_get_named($4, &proto_ospf), 1); };
|
{ ospf_sh_state(proto_get_named($4, &proto_ospf), 0, 1); };
|
||||||
|
|
||||||
|
CF_CLI(SHOW OSPF TOPOLOGY ALL, optsym opttext, [<name>], [[Show information about all OSPF network topology]])
|
||||||
|
{ ospf_sh_state(proto_get_named($5, &proto_ospf), 0, 0); };
|
||||||
|
|
||||||
|
CF_CLI_HELP(SHOW OSPF STATE, [all] [<name>], [[Show information about OSPF network state]])
|
||||||
|
|
||||||
|
CF_CLI(SHOW OSPF STATE, optsym opttext, [<name>], [[Show information about reachable OSPF network state]])
|
||||||
|
{ ospf_sh_state(proto_get_named($4, &proto_ospf), 1, 1); };
|
||||||
|
|
||||||
|
CF_CLI(SHOW OSPF STATE ALL, optsym opttext, [<name>], [[Show information about all OSPF network state]])
|
||||||
|
{ ospf_sh_state(proto_get_named($5, &proto_ospf), 1, 0); };
|
||||||
|
|
||||||
CF_CLI(SHOW OSPF LSADB, optsym opttext, [<name>], [[Show content of OSPF LSA database]])
|
CF_CLI(SHOW OSPF LSADB, optsym opttext, [<name>], [[Show content of OSPF LSA database]])
|
||||||
{ ospf_sh_lsadb(proto_get_named($4, &proto_ospf)); };
|
{ ospf_sh_lsadb(proto_get_named($4, &proto_ospf)); };
|
||||||
|
|
|
@ -260,6 +260,7 @@ ospf_iface_down(struct ospf_iface *ifa)
|
||||||
ifa->iface = NULL;
|
ifa->iface = NULL;
|
||||||
ifa->addr = NULL;
|
ifa->addr = NULL;
|
||||||
ifa->sk = NULL;
|
ifa->sk = NULL;
|
||||||
|
ifa->cost = 0;
|
||||||
ifa->vip = IPA_NONE;
|
ifa->vip = IPA_NONE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -445,27 +446,6 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, struct ifa *addr,
|
||||||
|
|
||||||
#ifdef OSPFv3
|
#ifdef OSPFv3
|
||||||
ifa->instance_id = ip->instance_id;
|
ifa->instance_id = ip->instance_id;
|
||||||
|
|
||||||
/*
|
|
||||||
addr = NULL;
|
|
||||||
if (ifa->type != OSPF_IT_VLINK)
|
|
||||||
{
|
|
||||||
struct ifa *a;
|
|
||||||
WALK_LIST(a, iface->addrs)
|
|
||||||
if (a->scope == SCOPE_LINK)
|
|
||||||
{
|
|
||||||
addr = a;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!addr)
|
|
||||||
{
|
|
||||||
log(L_ERR "%s: Missing link-local address on interface %s, declaring as stub", p->name, iface->name);
|
|
||||||
ifa->ioprob = OSPF_I_LL;
|
|
||||||
ifa->stub = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ip->type == OSPF_IT_UNDEF)
|
if (ip->type == OSPF_IT_UNDEF)
|
||||||
|
@ -824,5 +804,4 @@ ospf_iface_shutdown(struct ospf_iface *ifa)
|
||||||
{
|
{
|
||||||
init_list(&ifa->neigh_list);
|
init_list(&ifa->neigh_list);
|
||||||
hello_timer_hook(ifa->hello_timer);
|
hello_timer_hook(ifa->hello_timer);
|
||||||
ospf_sk_close(ifa);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,19 +45,16 @@ ospf_age(struct proto_ospf *po)
|
||||||
struct top_hash_entry *en, *nxt;
|
struct top_hash_entry *en, *nxt;
|
||||||
int flush = can_flush_lsa(po);
|
int flush = can_flush_lsa(po);
|
||||||
|
|
||||||
if (po->cleanup) OSPF_TRACE(D_EVENTS, "Running ospf_age cleanup");
|
|
||||||
|
|
||||||
WALK_SLIST_DELSAFE(en, nxt, po->lsal)
|
WALK_SLIST_DELSAFE(en, nxt, po->lsal)
|
||||||
{
|
{
|
||||||
if (po->cleanup)
|
if (po->calcrt)
|
||||||
{
|
{
|
||||||
|
/* Cleanup before ospf_rt_spf() */
|
||||||
en->color = OUTSPF;
|
en->color = OUTSPF;
|
||||||
en->dist = LSINFINITY;
|
en->dist = LSINFINITY;
|
||||||
en->nhi = NULL;
|
en->nhi = NULL;
|
||||||
en->nh = IPA_NONE;
|
en->nh = IPA_NONE;
|
||||||
en->lb = IPA_NONE;
|
en->lb = IPA_NONE;
|
||||||
DBG("Infinitying Type: %u, Id: %R, Rt: %R\n", en->lsa.type,
|
|
||||||
en->lsa.id, en->lsa.rt);
|
|
||||||
}
|
}
|
||||||
if (en->lsa.age == LSA_MAXAGE)
|
if (en->lsa.age == LSA_MAXAGE)
|
||||||
{
|
{
|
||||||
|
@ -88,9 +85,9 @@ ospf_age(struct proto_ospf *po)
|
||||||
en->lsa.age = LSA_MAXAGE;
|
en->lsa.age = LSA_MAXAGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
po->cleanup = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CPU_BIG_ENDIAN
|
||||||
void
|
void
|
||||||
htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
|
htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
|
||||||
{
|
{
|
||||||
|
@ -142,6 +139,7 @@ ntohlsab(void *n, void *h, u16 len)
|
||||||
for (i = 0; i < (len / sizeof(u32)); i++)
|
for (i = 0; i < (len / sizeof(u32)); i++)
|
||||||
hid[i] = ntohl(nid[i]);
|
hid[i] = ntohl(nid[i]);
|
||||||
}
|
}
|
||||||
|
#endif /* little endian */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void
|
void
|
||||||
|
@ -188,7 +186,7 @@ lsasum_calculate(struct ospf_lsa_header *h, void *body)
|
||||||
|
|
||||||
// log(L_WARN "Checksum %R %R %d start (len %d)", h->id, h->rt, h->type, length);
|
// log(L_WARN "Checksum %R %R %d start (len %d)", h->id, h->rt, h->type, length);
|
||||||
htonlsah(h, h);
|
htonlsah(h, h);
|
||||||
htonlsab(body, body, length - sizeof(struct ospf_lsa_header));
|
htonlsab1(body, length - sizeof(struct ospf_lsa_header));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
|
@ -202,7 +200,7 @@ lsasum_calculate(struct ospf_lsa_header *h, void *body)
|
||||||
// log(L_WARN "Checksum result %4x", h->checksum);
|
// log(L_WARN "Checksum result %4x", h->checksum);
|
||||||
|
|
||||||
ntohlsah(h, h);
|
ntohlsah(h, h);
|
||||||
ntohlsab(body, body, length - sizeof(struct ospf_lsa_header));
|
ntohlsab1(body, length - sizeof(struct ospf_lsa_header));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -10,10 +10,22 @@
|
||||||
#ifndef _BIRD_OSPF_LSALIB_H_
|
#ifndef _BIRD_OSPF_LSALIB_H_
|
||||||
#define _BIRD_OSPF_LSALIB_H_
|
#define _BIRD_OSPF_LSALIB_H_
|
||||||
|
|
||||||
|
#ifdef CPU_BIG_ENDIAN
|
||||||
|
static inline void htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n) { *n = *h; };
|
||||||
|
static inline void ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h) { *h = *n; };
|
||||||
|
static inline void htonlsab(void *h, void *n, u16 len) { memcpy(n, h, len); };
|
||||||
|
static inline void ntohlsab(void *n, void *h, u16 len) { memcpy(h, n, len); };
|
||||||
|
static inline void htonlsab1(void *h, u16 len) { };
|
||||||
|
static inline void ntohlsab1(void *n, u16 len) { };
|
||||||
|
#else
|
||||||
void htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n);
|
void htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n);
|
||||||
void ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h);
|
void ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h);
|
||||||
void htonlsab(void *h, void *n, u16 len);
|
void htonlsab(void *h, void *n, u16 len);
|
||||||
void ntohlsab(void *n, void *h, u16 len);
|
void ntohlsab(void *n, void *h, u16 len);
|
||||||
|
static inline void htonlsab1(void *h, u16 len) { htonlsab(h, h, len); };
|
||||||
|
static inline void ntohlsab1(void *n, u16 len) { ntohlsab(n, n, len); };
|
||||||
|
#endif
|
||||||
|
|
||||||
void lsasum_calculate(struct ospf_lsa_header *header, void *body);
|
void lsasum_calculate(struct ospf_lsa_header *header, void *body);
|
||||||
u16 lsasum_check(struct ospf_lsa_header *h, void *body);
|
u16 lsasum_check(struct ospf_lsa_header *h, void *body);
|
||||||
#define CMP_NEWER 1
|
#define CMP_NEWER 1
|
||||||
|
|
|
@ -536,27 +536,6 @@ find_neigh(struct ospf_iface *ifa, u32 rid)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Find a closest neighbor which is at least 2-Way */
|
|
||||||
struct ospf_neighbor *
|
|
||||||
find_neigh_noifa(struct proto_ospf *po, u32 rid)
|
|
||||||
{
|
|
||||||
struct ospf_neighbor *n = NULL, *m;
|
|
||||||
struct ospf_iface *ifa;
|
|
||||||
|
|
||||||
WALK_LIST(ifa, po->iface_list) if ((m = find_neigh(ifa, rid)) != NULL)
|
|
||||||
{
|
|
||||||
if (m->state >= NEIGHBOR_2WAY)
|
|
||||||
{
|
|
||||||
if (n == NULL)
|
|
||||||
n = m;
|
|
||||||
else if (m->ifa->cost < n->ifa->cost)
|
|
||||||
n = m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ospf_area *
|
struct ospf_area *
|
||||||
ospf_find_area(struct proto_ospf *po, u32 aid)
|
ospf_find_area(struct proto_ospf *po, u32 aid)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,7 +14,6 @@ struct ospf_neighbor *ospf_neighbor_new(struct ospf_iface *ifa);
|
||||||
void ospf_neigh_sm(struct ospf_neighbor *n, int event);
|
void ospf_neigh_sm(struct ospf_neighbor *n, int event);
|
||||||
void bdr_election(struct ospf_iface *ifa);
|
void bdr_election(struct ospf_iface *ifa);
|
||||||
struct ospf_neighbor *find_neigh(struct ospf_iface *ifa, u32 rid);
|
struct ospf_neighbor *find_neigh(struct ospf_iface *ifa, u32 rid);
|
||||||
struct ospf_neighbor *find_neigh_noifa(struct proto_ospf *po, u32 rid);
|
|
||||||
struct ospf_area *ospf_find_area(struct proto_ospf *po, u32 aid);
|
struct ospf_area *ospf_find_area(struct proto_ospf *po, u32 aid);
|
||||||
void ospf_neigh_remove(struct ospf_neighbor *n);
|
void ospf_neigh_remove(struct ospf_neighbor *n);
|
||||||
void ospf_sh_neigh_info(struct ospf_neighbor *n);
|
void ospf_sh_neigh_info(struct ospf_neighbor *n);
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
*
|
*
|
||||||
* The function area_disp() is
|
* The function area_disp() is
|
||||||
* responsible for late originating of router LSA and network LSA
|
* responsible for late originating of router LSA and network LSA
|
||||||
* and for cleanup after routing table calculation process in
|
* and for cleanup before routing table calculation process in
|
||||||
* the area.
|
* the area.
|
||||||
* To every &ospf_iface, we connect one or more
|
* To every &ospf_iface, we connect one or more
|
||||||
* &ospf_neighbor's -- a structure containing many timers and queues
|
* &ospf_neighbor's -- a structure containing many timers and queues
|
||||||
|
@ -161,7 +161,6 @@ ospf_start(struct proto *p)
|
||||||
fib_init(&po->rtf, p->pool, sizeof(ort), 16, ospf_rt_initort);
|
fib_init(&po->rtf, p->pool, sizeof(ort), 16, ospf_rt_initort);
|
||||||
po->areano = 0;
|
po->areano = 0;
|
||||||
po->gr = ospf_top_new(p->pool);
|
po->gr = ospf_top_new(p->pool);
|
||||||
po->cleanup = 1;
|
|
||||||
s_init_list(&(po->lsal));
|
s_init_list(&(po->lsal));
|
||||||
if (EMPTY_LIST(c->area_list))
|
if (EMPTY_LIST(c->area_list))
|
||||||
{
|
{
|
||||||
|
@ -1134,8 +1133,34 @@ lsa_compare_for_state(const void *p1, const void *p2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ext_compare_for_state(const void *p1, const void *p2)
|
||||||
|
{
|
||||||
|
struct top_hash_entry * he1 = * (struct top_hash_entry **) p1;
|
||||||
|
struct top_hash_entry * he2 = * (struct top_hash_entry **) p2;
|
||||||
|
struct ospf_lsa_header *lsa1 = &(he1->lsa);
|
||||||
|
struct ospf_lsa_header *lsa2 = &(he2->lsa);
|
||||||
|
|
||||||
|
if (lsa1->rt != lsa2->rt)
|
||||||
|
return lsa1->rt - lsa2->rt;
|
||||||
|
|
||||||
|
if (lsa1->id != lsa2->id)
|
||||||
|
return lsa1->id - lsa2->id;
|
||||||
|
|
||||||
|
return lsa1->sn - lsa2->sn;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
show_lsa_router(struct proto_ospf *po, struct top_hash_entry *he)
|
show_lsa_distance(struct top_hash_entry *he)
|
||||||
|
{
|
||||||
|
if (he->color == INSPF)
|
||||||
|
cli_msg(-1016, "\t\tdistance %u", he->dist);
|
||||||
|
else
|
||||||
|
cli_msg(-1016, "\t\tunreachable");
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
show_lsa_router(struct proto_ospf *po, struct top_hash_entry *he, int first, int verbose)
|
||||||
{
|
{
|
||||||
struct ospf_lsa_header *lsa = &(he->lsa);
|
struct ospf_lsa_header *lsa = &(he->lsa);
|
||||||
struct ospf_lsa_rt *rt = he->lsa_body;
|
struct ospf_lsa_rt *rt = he->lsa_body;
|
||||||
|
@ -1143,6 +1168,14 @@ show_lsa_router(struct proto_ospf *po, struct top_hash_entry *he)
|
||||||
int max = lsa_rt_count(lsa);
|
int max = lsa_rt_count(lsa);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
cli_msg(-1016, "");
|
||||||
|
cli_msg(-1016, "\trouter %R", he->lsa.rt);
|
||||||
|
show_lsa_distance(he);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < max; i++)
|
for (i = 0; i < max; i++)
|
||||||
if (rr[i].type == LSART_VLNK)
|
if (rr[i].type == LSART_VLNK)
|
||||||
cli_msg(-1016, "\t\tvlink %R metric %u", rr[i].id, rr[i].metric);
|
cli_msg(-1016, "\t\tvlink %R metric %u", rr[i].id, rr[i].metric);
|
||||||
|
@ -1175,6 +1208,9 @@ show_lsa_router(struct proto_ospf *po, struct top_hash_entry *he)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
|
if (!verbose)
|
||||||
|
return;
|
||||||
|
|
||||||
for (i = 0; i < max; i++)
|
for (i = 0; i < max; i++)
|
||||||
if (rr[i].type == LSART_STUB)
|
if (rr[i].type == LSART_STUB)
|
||||||
cli_msg(-1016, "\t\tstubnet %I/%d metric %u", ipa_from_u32(rr[i].id),
|
cli_msg(-1016, "\t\tstubnet %I/%d metric %u", ipa_from_u32(rr[i].id),
|
||||||
|
@ -1198,6 +1234,8 @@ show_lsa_network(struct top_hash_entry *he)
|
||||||
cli_msg(-1016, "\tnetwork [%R-%u]", lsa->rt, lsa->id);
|
cli_msg(-1016, "\tnetwork [%R-%u]", lsa->rt, lsa->id);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
show_lsa_distance(he);
|
||||||
|
|
||||||
for (i = 0; i < lsa_net_count(lsa); i++)
|
for (i = 0; i < lsa_net_count(lsa); i++)
|
||||||
cli_msg(-1016, "\t\trouter %R", ln->routers[i]);
|
cli_msg(-1016, "\t\trouter %R", ln->routers[i]);
|
||||||
}
|
}
|
||||||
|
@ -1251,6 +1289,8 @@ show_lsa_external(struct top_hash_entry *he)
|
||||||
int pxlen, ebit, rt_fwaddr_valid;
|
int pxlen, ebit, rt_fwaddr_valid;
|
||||||
u32 rt_tag, rt_metric;
|
u32 rt_tag, rt_metric;
|
||||||
|
|
||||||
|
he->domain = 0; /* Unmark the LSA */
|
||||||
|
|
||||||
rt_metric = ext->metric & METRIC_MASK;
|
rt_metric = ext->metric & METRIC_MASK;
|
||||||
ebit = ext->metric & LSA_EXT_EBIT;
|
ebit = ext->metric & LSA_EXT_EBIT;
|
||||||
#ifdef OSPFv2
|
#ifdef OSPFv2
|
||||||
|
@ -1289,7 +1329,7 @@ show_lsa_external(struct top_hash_entry *he)
|
||||||
|
|
||||||
#ifdef OSPFv3
|
#ifdef OSPFv3
|
||||||
static inline void
|
static inline void
|
||||||
show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *olsa)
|
show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *cnode)
|
||||||
{
|
{
|
||||||
struct ospf_lsa_prefix *px = he->lsa_body;
|
struct ospf_lsa_prefix *px = he->lsa_body;
|
||||||
ip_addr pxa;
|
ip_addr pxa;
|
||||||
|
@ -1299,10 +1339,14 @@ show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *olsa)
|
||||||
u32 *buf;
|
u32 *buf;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* We check whether given prefix-LSA is related to the last non-prefix-LSA */
|
/* We check whether given prefix-LSA is related to the current node */
|
||||||
if ((olsa == NULL) || (olsa->type != px->ref_type) || (olsa->rt != px->ref_rt) ||
|
if ((px->ref_type != cnode->type) || (px->ref_rt != cnode->rt))
|
||||||
!(((px->ref_type == LSA_T_RT) && (px->ref_id == 0)) ||
|
return;
|
||||||
((px->ref_type == LSA_T_NET) && (px->ref_id == olsa->id))))
|
|
||||||
|
if ((px->ref_type == LSA_T_RT) && (px->ref_id != 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((px->ref_type == LSA_T_NET) && (px->ref_id != cnode->id))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
buf = px->rest;
|
buf = px->rest;
|
||||||
|
@ -1319,18 +1363,14 @@ show_lsa_prefix(struct top_hash_entry *he, struct ospf_lsa_header *olsa)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
ospf_sh_state(struct proto *p, int verbose)
|
ospf_sh_state(struct proto *p, int verbose, int reachable)
|
||||||
{
|
{
|
||||||
struct proto_ospf *po = (struct proto_ospf *) p;
|
struct proto_ospf *po = (struct proto_ospf *) p;
|
||||||
struct top_graph *f = po->gr;
|
struct ospf_lsa_header *cnode = NULL;
|
||||||
unsigned int i, j1, j2;
|
int num = po->gr->hash_entries;
|
||||||
u32 last_rt = 0xFFFFFFFF;
|
unsigned int i, ix, j1, j2, jx;
|
||||||
u32 last_area = 0xFFFFFFFF;
|
u32 last_area = 0xFFFFFFFF;
|
||||||
|
|
||||||
#ifdef OSPFv3
|
|
||||||
struct ospf_lsa_header *olsa = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (p->proto_state != PS_UP)
|
if (p->proto_state != PS_UP)
|
||||||
{
|
{
|
||||||
cli_msg(-1016, "%s: is not up", p->name);
|
cli_msg(-1016, "%s: is not up", p->name);
|
||||||
|
@ -1338,10 +1378,14 @@ ospf_sh_state(struct proto *p, int verbose)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct top_hash_entry *hea[f->hash_entries];
|
/* We store interesting area-scoped LSAs in array hea and
|
||||||
|
global-scoped (LSA_T_EXT) LSAs in array hex */
|
||||||
|
|
||||||
|
struct top_hash_entry *hea[num];
|
||||||
|
struct top_hash_entry *hex[verbose ? num : 0];
|
||||||
struct top_hash_entry *he;
|
struct top_hash_entry *he;
|
||||||
|
|
||||||
j1 = j2 = 0;
|
j1 = j2 = jx = 0;
|
||||||
WALK_SLIST(he, po->lsal)
|
WALK_SLIST(he, po->lsal)
|
||||||
{
|
{
|
||||||
int accept;
|
int accept;
|
||||||
|
@ -1355,13 +1399,18 @@ ospf_sh_state(struct proto *p, int verbose)
|
||||||
|
|
||||||
case LSA_T_SUM_NET:
|
case LSA_T_SUM_NET:
|
||||||
case LSA_T_SUM_RT:
|
case LSA_T_SUM_RT:
|
||||||
case LSA_T_EXT:
|
|
||||||
#ifdef OSPFv3
|
#ifdef OSPFv3
|
||||||
case LSA_T_PREFIX:
|
case LSA_T_PREFIX:
|
||||||
#endif
|
#endif
|
||||||
accept = verbose;
|
accept = verbose;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case LSA_T_EXT:
|
||||||
|
if (verbose)
|
||||||
|
{
|
||||||
|
he->domain = 1; /* Abuse domain field to mark the LSA */
|
||||||
|
hex[jx++] = he;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
accept = 0;
|
accept = 0;
|
||||||
}
|
}
|
||||||
|
@ -1372,66 +1421,137 @@ ospf_sh_state(struct proto *p, int verbose)
|
||||||
j2++;
|
j2++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((j1 + j2) != f->hash_entries)
|
if ((j1 + j2) != num)
|
||||||
die("Fatal mismatch");
|
die("Fatal mismatch");
|
||||||
|
|
||||||
qsort(hea, j1, sizeof(struct top_hash_entry *), lsa_compare_for_state);
|
qsort(hea, j1, sizeof(struct top_hash_entry *), lsa_compare_for_state);
|
||||||
|
qsort(hex, jx, sizeof(struct top_hash_entry *), ext_compare_for_state);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This code is a bit tricky, we have a primary LSAs (router and
|
||||||
|
* network) that are presented as a node, and secondary LSAs that
|
||||||
|
* are presented as a part of a primary node. cnode represents an
|
||||||
|
* currently opened node (whose header was presented). The LSAs are
|
||||||
|
* sorted to get secondary LSAs just after related primary LSA (if
|
||||||
|
* available). We present secondary LSAs only when related primary
|
||||||
|
* LSA is opened.
|
||||||
|
*
|
||||||
|
* AS-external LSAs are stored separately as they might be presented
|
||||||
|
* several times (for each area when related ASBR is opened). When
|
||||||
|
* the node is closed, related external routes are presented. We
|
||||||
|
* also have to take into account that in OSPFv3, there might be
|
||||||
|
* more router-LSAs and only the first should be considered as a
|
||||||
|
* primary. This is handled by not closing old router-LSA when next
|
||||||
|
* one is processed (which is not opened because there is already
|
||||||
|
* one opened).
|
||||||
|
*/
|
||||||
|
|
||||||
|
ix = 0;
|
||||||
for (i = 0; i < j1; i++)
|
for (i = 0; i < j1; i++)
|
||||||
{
|
{
|
||||||
if (last_area != hea[i]->domain)
|
he = hea[i];
|
||||||
|
|
||||||
|
/* If there is no opened node, we open the LSA (if appropriate) or skip to the next one */
|
||||||
|
if (!cnode)
|
||||||
|
{
|
||||||
|
if (((he->lsa.type == LSA_T_RT) || (he->lsa.type == LSA_T_NET))
|
||||||
|
&& ((he->color == INSPF) || !reachable))
|
||||||
|
{
|
||||||
|
cnode = &(he->lsa);
|
||||||
|
|
||||||
|
if (he->domain != last_area)
|
||||||
{
|
{
|
||||||
cli_msg(-1016, "");
|
cli_msg(-1016, "");
|
||||||
cli_msg(-1016, "area %R", hea[i]->domain);
|
cli_msg(-1016, "area %R", he->domain);
|
||||||
last_area = hea[i]->domain;
|
last_area = he->domain;
|
||||||
last_rt = 0xFFFFFFFF;
|
ix = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((hea[i]->lsa.rt != last_rt) && (hea[i]->lsa.type != LSA_T_NET)
|
ASSERT(cnode && (he->domain == last_area) && (he->lsa.rt == cnode->rt));
|
||||||
#ifdef OSPFv3
|
|
||||||
&& (hea[i]->lsa.type != LSA_T_PREFIX)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
cli_msg(-1016, "");
|
|
||||||
cli_msg(-1016, (hea[i]->lsa.type != LSA_T_EXT) ? "\trouter %R" : "\txrouter %R", hea[i]->lsa.rt);
|
|
||||||
last_rt = hea[i]->lsa.rt;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (hea[i]->lsa.type)
|
switch (he->lsa.type)
|
||||||
{
|
{
|
||||||
case LSA_T_RT:
|
case LSA_T_RT:
|
||||||
show_lsa_router(po, hea[i]);
|
show_lsa_router(po, he, he->lsa.id == cnode->id, verbose);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LSA_T_NET:
|
case LSA_T_NET:
|
||||||
show_lsa_network(hea[i]);
|
show_lsa_network(he);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LSA_T_SUM_NET:
|
case LSA_T_SUM_NET:
|
||||||
show_lsa_sum_net(hea[i]);
|
if (cnode->type == LSA_T_RT)
|
||||||
|
show_lsa_sum_net(he);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LSA_T_SUM_RT:
|
case LSA_T_SUM_RT:
|
||||||
show_lsa_sum_rt(hea[i]);
|
if (cnode->type == LSA_T_RT)
|
||||||
break;
|
show_lsa_sum_rt(he);
|
||||||
|
|
||||||
case LSA_T_EXT:
|
|
||||||
show_lsa_external(hea[i]);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#ifdef OSPFv3
|
#ifdef OSPFv3
|
||||||
case LSA_T_PREFIX:
|
case LSA_T_PREFIX:
|
||||||
show_lsa_prefix(hea[i], olsa);
|
show_lsa_prefix(he, cnode);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
case LSA_T_EXT:
|
||||||
|
show_lsa_external(he);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OSPFv3
|
/* In these cases, we close the current node */
|
||||||
if (hea[i]->lsa.type != LSA_T_PREFIX)
|
if ((i+1 == j1)
|
||||||
olsa = &(hea[i]->lsa);
|
|| (hea[i+1]->domain != last_area)
|
||||||
#endif
|
|| (hea[i+1]->lsa.rt != cnode->rt)
|
||||||
|
|| (hea[i+1]->lsa.type == LSA_T_NET))
|
||||||
|
{
|
||||||
|
while ((ix < jx) && (hex[ix]->lsa.rt < cnode->rt))
|
||||||
|
ix++;
|
||||||
|
|
||||||
|
while ((ix < jx) && (hex[ix]->lsa.rt == cnode->rt))
|
||||||
|
show_lsa_external(hex[ix++]);
|
||||||
|
|
||||||
|
cnode = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int hdr = 0;
|
||||||
|
u32 last_rt = 0xFFFFFFFF;
|
||||||
|
for (ix = 0; ix < jx; ix++)
|
||||||
|
{
|
||||||
|
he = hex[ix];
|
||||||
|
|
||||||
|
/* If it is still marked, we show it now. */
|
||||||
|
if (he->domain)
|
||||||
|
{
|
||||||
|
he->domain = 0;
|
||||||
|
|
||||||
|
if ((he->color != INSPF) && reachable)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!hdr)
|
||||||
|
{
|
||||||
|
cli_msg(-1016, "");
|
||||||
|
cli_msg(-1016, "other ASBRs");
|
||||||
|
hdr = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (he->lsa.rt != last_rt)
|
||||||
|
{
|
||||||
|
cli_msg(-1016, "");
|
||||||
|
cli_msg(-1016, "\trouter %R", he->lsa.rt);
|
||||||
|
last_rt = he->lsa.rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
show_lsa_external(he);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cli_msg(0, "");
|
cli_msg(0, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1468,7 +1588,7 @@ void
|
||||||
ospf_sh_lsadb(struct proto *p)
|
ospf_sh_lsadb(struct proto *p)
|
||||||
{
|
{
|
||||||
struct proto_ospf *po = (struct proto_ospf *) p;
|
struct proto_ospf *po = (struct proto_ospf *) p;
|
||||||
struct top_graph *f = po->gr;
|
int num = po->gr->hash_entries;
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
int last_dscope = -1;
|
int last_dscope = -1;
|
||||||
u32 last_domain = 0;
|
u32 last_domain = 0;
|
||||||
|
@ -1480,14 +1600,14 @@ ospf_sh_lsadb(struct proto *p)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct top_hash_entry *hea[f->hash_entries];
|
struct top_hash_entry *hea[num];
|
||||||
struct top_hash_entry *he;
|
struct top_hash_entry *he;
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
WALK_SLIST(he, po->lsal)
|
WALK_SLIST(he, po->lsal)
|
||||||
hea[j++] = he;
|
hea[j++] = he;
|
||||||
|
|
||||||
if (j != f->hash_entries)
|
if (j != num)
|
||||||
die("Fatal mismatch");
|
die("Fatal mismatch");
|
||||||
|
|
||||||
qsort(hea, j, sizeof(struct top_hash_entry *), lsa_compare_for_lsadb);
|
qsort(hea, j, sizeof(struct top_hash_entry *), lsa_compare_for_lsadb);
|
||||||
|
|
|
@ -722,7 +722,6 @@ struct proto_ospf
|
||||||
slist lsal; /* List of all LSA's */
|
slist lsal; /* List of all LSA's */
|
||||||
int calcrt; /* Routing table calculation scheduled?
|
int calcrt; /* Routing table calculation scheduled?
|
||||||
0=no, 1=normal, 2=forced reload */
|
0=no, 1=normal, 2=forced reload */
|
||||||
int cleanup; /* Should I cleanup after RT calculation? */
|
|
||||||
list iface_list; /* Interfaces we really use */
|
list iface_list; /* Interfaces we really use */
|
||||||
list area_list;
|
list area_list;
|
||||||
int areano; /* Number of area I belong to */
|
int areano; /* Number of area I belong to */
|
||||||
|
@ -808,7 +807,7 @@ static inline void schedule_link_lsa(struct ospf_iface *ifa UNUSED) {}
|
||||||
void ospf_sh_neigh(struct proto *p, char *iff);
|
void ospf_sh_neigh(struct proto *p, char *iff);
|
||||||
void ospf_sh(struct proto *p);
|
void ospf_sh(struct proto *p);
|
||||||
void ospf_sh_iface(struct proto *p, char *iff);
|
void ospf_sh_iface(struct proto *p, char *iff);
|
||||||
void ospf_sh_state(struct proto *p, int verbose);
|
void ospf_sh_state(struct proto *p, int verbose, int reachable);
|
||||||
void ospf_sh_lsadb(struct proto *p);
|
void ospf_sh_lsadb(struct proto *p);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,7 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
|
||||||
}
|
}
|
||||||
password_cpy(pkt->u.password, passwd->password, sizeof(union ospf_auth));
|
password_cpy(pkt->u.password, passwd->password, sizeof(union ospf_auth));
|
||||||
case OSPF_AUTH_NONE:
|
case OSPF_AUTH_NONE:
|
||||||
|
pkt->checksum = 0;
|
||||||
pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet) -
|
pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet) -
|
||||||
sizeof(union ospf_auth), (pkt + 1),
|
sizeof(union ospf_auth), (pkt + 1),
|
||||||
ntohs(pkt->length) -
|
ntohs(pkt->length) -
|
||||||
|
@ -241,6 +242,19 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef OSPFv2
|
||||||
|
static inline struct ospf_neighbor *
|
||||||
|
find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
|
||||||
|
{
|
||||||
|
struct ospf_neighbor *n;
|
||||||
|
WALK_LIST(n, ifa->neigh_list)
|
||||||
|
if (ipa_equal(n->ip, ip))
|
||||||
|
return n;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ospf_rx_hook
|
* ospf_rx_hook
|
||||||
|
@ -418,10 +432,16 @@ ospf_rx_hook(sock *sk, int size)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is deviation from RFC 2328 - neighbours should be identified by
|
#ifdef OSPFv2
|
||||||
* IP address on broadcast and NBMA networks.
|
/* In OSPFv2, neighbors are identified by either IP or Router ID, base on network type */
|
||||||
*/
|
struct ospf_neighbor *n;
|
||||||
|
if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
|
||||||
|
n = find_neigh_by_ip(ifa, sk->faddr);
|
||||||
|
else
|
||||||
|
n = find_neigh(ifa, rid);
|
||||||
|
#else
|
||||||
struct ospf_neighbor *n = find_neigh(ifa, rid);
|
struct ospf_neighbor *n = find_neigh(ifa, rid);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(!n && (ps->type != HELLO_P))
|
if(!n && (ps->type != HELLO_P))
|
||||||
{
|
{
|
||||||
|
|
1007
proto/ospf/rt.c
1007
proto/ospf/rt.c
File diff suppressed because it is too large
Load diff
|
@ -18,21 +18,30 @@ typedef struct orta
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
u32 options;
|
u32 options;
|
||||||
/* router-LSA style options (for ORT_ROUTER), with V,E,B bits.
|
/*
|
||||||
In OSPFv2, ASBRs from another areas (that we know from rt-summary-lsa),
|
* For ORT_ROUTER routes, options field are router-LSA style
|
||||||
have just ORTA_ASBR in options, their real options are unknown */
|
* options, with V,E,B bits. In OSPFv2, ASBRs from another areas
|
||||||
|
* (that we know from rt-summary-lsa) have just ORTA_ASBR in
|
||||||
|
* options, their real options are unknown.
|
||||||
|
*/
|
||||||
#define ORTA_ASBR OPT_RT_E
|
#define ORTA_ASBR OPT_RT_E
|
||||||
#define ORTA_ABR OPT_RT_B
|
#define ORTA_ABR OPT_RT_B
|
||||||
struct ospf_area *oa;
|
/*
|
||||||
|
* For ORT_NET routes, the field is almost unused with one
|
||||||
|
* exception: ORTA_PREF for external routes means that the route is
|
||||||
|
* preferred in AS external route selection according to 16.4.1. -
|
||||||
|
* it is intra-area path using non-backbone area. In other words,
|
||||||
|
* the forwarding address (or ASBR if forwarding address is zero) is
|
||||||
|
* intra-area (type == RTS_OSPF) and its area is not a backbone.
|
||||||
|
*/
|
||||||
|
#define ORTA_PREF 0x80000000
|
||||||
u32 metric1;
|
u32 metric1;
|
||||||
u32 metric2;
|
u32 metric2;
|
||||||
ip_addr nh; /* Next hop */
|
|
||||||
struct ospf_iface *ifa; /* Outgoing interface */
|
|
||||||
struct top_hash_entry *ar; /* Advertising router (or ABR) */
|
|
||||||
u32 tag;
|
u32 tag;
|
||||||
u32 rid; /* Router ID of real advertising router */
|
u32 rid; /* Router ID of real advertising router */
|
||||||
/* For ext-LSA from different area, 'ar' is a type 1 LSA of ABR.
|
struct ospf_area *oa;
|
||||||
Router ID of real advertising router is stored in 'rid'. */
|
struct ospf_iface *ifa; /* Outgoing interface */
|
||||||
|
ip_addr nh; /* Next hop */
|
||||||
}
|
}
|
||||||
orta;
|
orta;
|
||||||
|
|
||||||
|
@ -41,7 +50,6 @@ typedef struct ort
|
||||||
struct fib_node fn;
|
struct fib_node fn;
|
||||||
orta n;
|
orta n;
|
||||||
orta o;
|
orta o;
|
||||||
struct ort *efn; /* For RFC1583 */
|
|
||||||
}
|
}
|
||||||
ort;
|
ort;
|
||||||
|
|
||||||
|
|
|
@ -1114,6 +1114,8 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
||||||
struct proto_ospf *po = oa->po;
|
struct proto_ospf *po = oa->po;
|
||||||
struct ospf_iface *ifa;
|
struct ospf_iface *ifa;
|
||||||
struct ospf_lsa_prefix *lp;
|
struct ospf_lsa_prefix *lp;
|
||||||
|
struct ifa *vlink_addr = NULL;
|
||||||
|
int host_addr = 0;
|
||||||
int net_lsa;
|
int net_lsa;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
u8 flags;
|
u8 flags;
|
||||||
|
@ -1139,10 +1141,15 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
||||||
struct ifa *a;
|
struct ifa *a;
|
||||||
WALK_LIST(a, ifa->iface->addrs)
|
WALK_LIST(a, ifa->iface->addrs)
|
||||||
{
|
{
|
||||||
if (((a->pxlen < MAX_PREFIX_LENGTH) && net_lsa) ||
|
if ((a->flags & IA_SECONDARY) ||
|
||||||
(a->flags & IA_SECONDARY) ||
|
|
||||||
(a->flags & IA_UNNUMBERED) ||
|
(a->flags & IA_UNNUMBERED) ||
|
||||||
(a->scope <= SCOPE_LINK) ||
|
(a->scope <= SCOPE_LINK))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!vlink_addr)
|
||||||
|
vlink_addr = a;
|
||||||
|
|
||||||
|
if (((a->pxlen < MAX_PREFIX_LENGTH) && net_lsa) ||
|
||||||
configured_stubnet(oa, a))
|
configured_stubnet(oa, a))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1150,10 +1157,20 @@ originate_prefix_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
||||||
put_ipv6_prefix(lsab_alloc(po, IPV6_PREFIX_SPACE(a->pxlen)),
|
put_ipv6_prefix(lsab_alloc(po, IPV6_PREFIX_SPACE(a->pxlen)),
|
||||||
a->ip, a->pxlen, flags, ifa->cost);
|
a->ip, a->pxlen, flags, ifa->cost);
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
|
if (flags & OPT_PX_LA)
|
||||||
|
host_addr = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME Handle vlinks? see RFC5340, page 38 */
|
/* If there are some configured vlinks, add some global address,
|
||||||
|
which will be used as a vlink endpoint. */
|
||||||
|
if (!EMPTY_LIST(oa->ac->vlink_list) && !host_addr && vlink_addr)
|
||||||
|
{
|
||||||
|
put_ipv6_prefix(lsab_alloc(po, IPV6_PREFIX_SPACE(MAX_PREFIX_LENGTH)),
|
||||||
|
vlink_addr->ip, MAX_PREFIX_LENGTH, OPT_PX_LA, 0);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
struct ospf_stubnet_config *sn;
|
struct ospf_stubnet_config *sn;
|
||||||
WALK_LIST(sn, oa->ac->stubnet_list)
|
WALK_LIST(sn, oa->ac->stubnet_list)
|
||||||
|
@ -1227,6 +1244,7 @@ prefix_advance(u32 *buf)
|
||||||
return buf + IPV6_PREFIX_WORDS(pxl);
|
return buf + IPV6_PREFIX_WORDS(pxl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME eliminate items wit LA bit set? see 4.4.3.9 */
|
||||||
static void
|
static void
|
||||||
add_prefix(struct proto_ospf *po, u32 *px, int offset, int *pxc)
|
add_prefix(struct proto_ospf *po, u32 *px, int offset, int *pxc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,8 +21,11 @@ struct top_hash_entry
|
||||||
void *lsa_body;
|
void *lsa_body;
|
||||||
bird_clock_t inst_t; /* Time of installation into DB */
|
bird_clock_t inst_t; /* Time of installation into DB */
|
||||||
ip_addr nh; /* Next hop */
|
ip_addr nh; /* Next hop */
|
||||||
ip_addr lb; /* Link back */
|
ip_addr lb; /* In OSPFv2, link back address. In OSPFv3, any global address in the area useful for vlinks */
|
||||||
struct ospf_iface *nhi; /* Next hop interface */
|
struct ospf_iface *nhi; /* Next hop interface - valid only in ospf_rt_spf()*/
|
||||||
|
#ifdef OSPFv3
|
||||||
|
u32 lb_id; /* Interface ID of link back iface (for bcast or NBMA networks) */
|
||||||
|
#endif
|
||||||
u32 dist; /* Distance from the root */
|
u32 dist; /* Distance from the root */
|
||||||
u16 ini_age;
|
u16 ini_age;
|
||||||
u8 color;
|
u8 color;
|
||||||
|
|
|
@ -7,6 +7,10 @@
|
||||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Unfortunately, some glibc versions hide parts of RFC 3542 API
|
||||||
|
if _GNU_SOURCE is not defined. */
|
||||||
|
#define _GNU_SOURCE 1
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -668,6 +672,16 @@ get_sockaddr(struct sockaddr_in *sa, ip_addr *a, unsigned *port, int check)
|
||||||
#define CMSG_RX_SPACE CMSG_SPACE(sizeof(struct in6_pktinfo))
|
#define CMSG_RX_SPACE CMSG_SPACE(sizeof(struct in6_pktinfo))
|
||||||
#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in6_pktinfo))
|
#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in6_pktinfo))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RFC 2292 uses IPV6_PKTINFO for both the socket option and the cmsg
|
||||||
|
* type, RFC 3542 changed the socket option to IPV6_RECVPKTINFO. If we
|
||||||
|
* don't have IPV6_RECVPKTINFO we suppose the OS implements the older
|
||||||
|
* RFC and we use IPV6_PKTINFO.
|
||||||
|
*/
|
||||||
|
#ifndef IPV6_RECVPKTINFO
|
||||||
|
#define IPV6_RECVPKTINFO IPV6_PKTINFO
|
||||||
|
#endif
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
sysio_register_cmsgs(sock *s)
|
sysio_register_cmsgs(sock *s)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue