Changes OSPF to generate stub networks for non-primary addresses.
Also does some reorganization in RT LSA announcement.
This commit is contained in:
parent
b99d378698
commit
3d15dcdb1c
6 changed files with 184 additions and 109 deletions
|
@ -327,6 +327,42 @@ mb_allocz(pool *p, unsigned size)
|
|||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* mb_realloc - reallocate a memory block
|
||||
* @p: pool
|
||||
* @m: memory block
|
||||
* @size: new size of the block
|
||||
*
|
||||
* mb_realloc() changes the size of the memory block @m to a given size.
|
||||
* The contents will be unchanged to the minimum of the old and new sizes;
|
||||
* newly allocated memory will be uninitialized. If @m is NULL, the call
|
||||
* is equivalent to mb_alloc(@p, @size).
|
||||
*
|
||||
* Like mb_alloc(), mb_realloc() also returns a pointer to the memory
|
||||
* chunk , not to the resource, hence you have to free it using
|
||||
* mb_free(), not rfree().
|
||||
*/
|
||||
void *
|
||||
mb_realloc(pool *p, void *m, unsigned size)
|
||||
{
|
||||
struct mblock *ob = NULL;
|
||||
|
||||
if (m)
|
||||
{
|
||||
ob = SKIP_BACK(struct mblock, data, m);
|
||||
if (ob->r.n.next)
|
||||
rem_node(&ob->r.n);
|
||||
}
|
||||
|
||||
struct mblock *b = xrealloc(ob, sizeof(struct mblock) + size);
|
||||
|
||||
b->r.class = &mb_class;
|
||||
add_tail(&p->inside, &b->r.n);
|
||||
b->size = size;
|
||||
return b->data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* mb_free - free a memory block
|
||||
* @m: memory block
|
||||
|
@ -339,3 +375,4 @@ mb_free(void *m)
|
|||
struct mblock *b = SKIP_BACK(struct mblock, data, m);
|
||||
rfree(b);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@ extern pool root_pool;
|
|||
|
||||
void *mb_alloc(pool *, unsigned size);
|
||||
void *mb_allocz(pool *, unsigned size);
|
||||
void *mb_realloc(pool *p, void *m, unsigned size);
|
||||
void mb_free(void *);
|
||||
|
||||
/* Memory pools with linear allocation */
|
||||
|
@ -75,12 +76,13 @@ void sl_free(slab *, void *);
|
|||
#ifdef HAVE_LIBDMALLOC
|
||||
/*
|
||||
* The standard dmalloc macros tend to produce lots of namespace
|
||||
* conflicts and we use only xmalloc and xfree, so we can define
|
||||
* the stubs ourselves.
|
||||
* conflicts and we use only xmalloc, xrealloc and xfree, so we
|
||||
* can define the stubs ourselves.
|
||||
*/
|
||||
#define DMALLOC_DISABLE
|
||||
#include <dmalloc.h>
|
||||
#define xmalloc(size) _xmalloc_leap(__FILE__, __LINE__, size)
|
||||
#define xrealloc(size) _xrealloc_leap(__FILE__, __LINE__, size)
|
||||
#define xfree(ptr) _xfree_leap(__FILE__, __LINE__, ptr)
|
||||
#else
|
||||
/*
|
||||
|
@ -89,7 +91,9 @@ void sl_free(slab *, void *);
|
|||
* the renaming.
|
||||
*/
|
||||
#define xmalloc bird_xmalloc
|
||||
#define xrealloc bird_xrealloc
|
||||
void *xmalloc(unsigned);
|
||||
void *xrealloc(void *, unsigned);
|
||||
#define xfree(x) free(x)
|
||||
#endif
|
||||
|
||||
|
|
|
@ -32,4 +32,24 @@ xmalloc(unsigned size)
|
|||
die("Unable to allocate %d bytes of memory", size);
|
||||
}
|
||||
|
||||
/**
|
||||
* xrealloc - realloc with checking
|
||||
* @ptr: original memory block
|
||||
* @size: block size
|
||||
*
|
||||
* This function is equivalent to realloc() except that in case of
|
||||
* failure it calls die() to quit the program instead of returning
|
||||
* a %NULL pointer.
|
||||
*
|
||||
* Wherever possible, please use the memory resources instead.
|
||||
*/
|
||||
void *
|
||||
xrealloc(void *ptr, unsigned size)
|
||||
{
|
||||
void *p = realloc(ptr, size);
|
||||
if (p)
|
||||
return p;
|
||||
die("Unable to allocate %d bytes of memory", size);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -76,6 +76,9 @@
|
|||
#include <stdlib.h>
|
||||
#include "ospf.h"
|
||||
|
||||
|
||||
static void ospf_rt_notify(struct proto *p, net * n, rte * new, rte * old UNUSED, ea_list * attrs);
|
||||
static void ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a);
|
||||
static int ospf_rte_better(struct rte *new, struct rte *old);
|
||||
static int ospf_rte_same(struct rte *new, struct rte *old);
|
||||
static void ospf_disp(timer *timer);
|
||||
|
@ -124,6 +127,9 @@ ospf_start(struct proto *p)
|
|||
po->disp_timer->hook = ospf_disp;
|
||||
po->disp_timer->recurrent = po->tick;
|
||||
tm_start(po->disp_timer, 1);
|
||||
po->lsab_size = 256;
|
||||
po->lsab_used = 0;
|
||||
po->lsab = mb_alloc(p->pool, po->lsab_size);
|
||||
init_list(&(po->iface_list));
|
||||
init_list(&(po->area_list));
|
||||
fib_init(&po->rtf, p->pool, sizeof(ort), 16, ospf_rt_initort);
|
||||
|
@ -227,6 +233,7 @@ ospf_init(struct proto_config *c)
|
|||
p->accept_ra_types = RA_OPTIMAL;
|
||||
p->rt_notify = ospf_rt_notify;
|
||||
p->if_notify = ospf_iface_notify;
|
||||
p->ifa_notify = ospf_ifa_notify;
|
||||
p->rte_better = ospf_rte_better;
|
||||
p->rte_same = ospf_rte_same;
|
||||
|
||||
|
@ -429,7 +436,7 @@ ospf_shutdown(struct proto *p)
|
|||
return PS_DOWN;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
ospf_rt_notify(struct proto *p, net * n, rte * new, rte * old UNUSED,
|
||||
ea_list * attrs)
|
||||
{
|
||||
|
@ -473,6 +480,25 @@ ospf_rt_notify(struct proto *p, net * n, rte * new, rte * old UNUSED,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ospf_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
|
||||
{
|
||||
struct proto_ospf *po = (struct proto_ospf *) p;
|
||||
struct ospf_iface *ifa;
|
||||
|
||||
if ((a->flags & IA_SECONDARY) || (a->flags & IA_UNNUMBERED))
|
||||
return;
|
||||
|
||||
WALK_LIST(ifa, po->iface_list)
|
||||
{
|
||||
if (ifa->iface == a->iface)
|
||||
{
|
||||
schedule_rt_lsa(ifa->oa);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ospf_get_status(struct proto *p, byte * buf)
|
||||
{
|
||||
|
|
|
@ -550,6 +550,8 @@ struct proto_ospf
|
|||
int rfc1583; /* RFC1583 compatibility */
|
||||
int ebit; /* Did I originate any ext lsa? */
|
||||
struct ospf_area *backbone; /* If exists */
|
||||
void *lsab; /* LSA buffer used when originating router LSAs */
|
||||
int lsab_size, lsab_used;
|
||||
};
|
||||
|
||||
struct ospf_iface_patt
|
||||
|
@ -585,8 +587,6 @@ int ospf_import_control(struct proto *p, rte **new, ea_list **attrs,
|
|||
struct linpool *pool);
|
||||
struct ea_list *ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool);
|
||||
void ospf_store_tmp_attrs(struct rte *rt, struct ea_list *attrs);
|
||||
void ospf_rt_notify(struct proto *p, net *n, rte *new, rte *old,
|
||||
ea_list * attrs);
|
||||
void schedule_rt_lsa(struct ospf_area *oa);
|
||||
void schedule_rtcalc(struct proto_ospf *po);
|
||||
void schedule_net_lsa(struct ospf_iface *ifa);
|
||||
|
|
|
@ -22,123 +22,99 @@
|
|||
|
||||
int ptp_unnumbered_stub_lsa = 0;
|
||||
|
||||
static void *
|
||||
lsab_alloc(struct proto_ospf *po, unsigned size)
|
||||
{
|
||||
unsigned offset = po->lsab_used;
|
||||
po->lsab_used += size;
|
||||
if (po->lsab_used > po->lsab_size)
|
||||
{
|
||||
po->lsab_size = MAX(po->lsab_used, 2 * po->lsab_size);
|
||||
po->lsab = mb_realloc(po->proto.pool, po->lsab, po->lsab_size);
|
||||
}
|
||||
return ((byte *) po->lsab) + offset;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
lsab_allocz(struct proto_ospf *po, unsigned size)
|
||||
{
|
||||
void *r = lsab_alloc(po, size);
|
||||
bzero(r, size);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
lsab_flush(struct proto_ospf *po)
|
||||
{
|
||||
void *r = mb_alloc(po->proto.pool, po->lsab_size);
|
||||
memcpy(r, po->lsab, po->lsab_used);
|
||||
po->lsab_used = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
|
||||
{
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct ospf_iface *ifa;
|
||||
int j = 0, k = 0;
|
||||
u16 i = 0;
|
||||
int i = 0, j = 0, k = 0, bitv = 0;
|
||||
struct ospf_lsa_rt *rt;
|
||||
struct ospf_lsa_rt_link *ln, *ln_after;
|
||||
struct ospf_lsa_rt_link *ln;
|
||||
struct ospf_neighbor *neigh;
|
||||
|
||||
DBG("%s: Originating RT_lsa body for area \"%I\".\n", po->proto.name,
|
||||
oa->areaid);
|
||||
|
||||
WALK_LIST(ifa, po->iface_list)
|
||||
{
|
||||
if ((ifa->oa == oa) && (ifa->state != OSPF_IS_DOWN))
|
||||
{
|
||||
i++;
|
||||
if ((ifa->type == OSPF_IT_PTP) && (ifa->state == OSPF_IS_PTP) &&
|
||||
(ptp_unnumbered_stub_lsa || !(ifa->iface->addr->flags & IA_UNNUMBERED)))
|
||||
i++;
|
||||
}
|
||||
}
|
||||
rt = mb_allocz(po->proto.pool, sizeof(struct ospf_lsa_rt) +
|
||||
i * sizeof(struct ospf_lsa_rt_link));
|
||||
ASSERT(po->lsab_used == 0);
|
||||
rt = lsab_allocz(po, sizeof(struct ospf_lsa_rt));
|
||||
if (po->areano > 1)
|
||||
rt->veb.bit.b = 1;
|
||||
if ((po->ebit) && (!oa->stub))
|
||||
rt->veb.bit.e = 1;
|
||||
ln = (struct ospf_lsa_rt_link *) (rt + 1);
|
||||
ln_after = ln + i;
|
||||
rt = NULL; /* buffer might be reallocated later */
|
||||
|
||||
WALK_LIST(ifa, po->iface_list)
|
||||
{
|
||||
if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) && (!EMPTY_LIST(ifa->neigh_list)))
|
||||
int master = 0;
|
||||
|
||||
if ((ifa->type == OSPF_IT_VLINK) && (ifa->voa == oa) &&
|
||||
(!EMPTY_LIST(ifa->neigh_list)))
|
||||
{
|
||||
neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
|
||||
if ((neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
|
||||
rt->veb.bit.v = 1;
|
||||
bitv = 1;
|
||||
}
|
||||
|
||||
if ((ifa->oa != oa) || (ifa->state == OSPF_IS_DOWN))
|
||||
continue;
|
||||
|
||||
if (ln == ln_after)
|
||||
die("LSA space overflow");
|
||||
/* BIRD does not support interface loops */
|
||||
ASSERT(ifa->state != OSPF_IS_LOOP);
|
||||
|
||||
if (ifa->state == OSPF_IS_LOOP)
|
||||
{
|
||||
ln->type = 3;
|
||||
ln->id = ipa_to_u32(ifa->iface->addr->ip);
|
||||
ln->data = 0xffffffff;
|
||||
ln->metric = 0;
|
||||
ln->notos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ifa->type)
|
||||
{
|
||||
case OSPF_IT_PTP: /* rfc2328 - pg126 */
|
||||
case OSPF_IT_PTP: /* RFC2328 - 12.4.1.1 */
|
||||
neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
|
||||
if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL))
|
||||
{
|
||||
ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
|
||||
ln->type = LSART_PTP;
|
||||
ln->id = neigh->rid;
|
||||
ln->data = (ifa->iface->addr->flags & IA_UNNUMBERED) ?
|
||||
ifa->iface->index : ipa_to_u32(ifa->iface->addr->ip);
|
||||
ln->metric = ifa->cost;
|
||||
ln->notos = 0;
|
||||
if (ifa->iface->addr->flags & IA_UNNUMBERED)
|
||||
{
|
||||
ln->data = ifa->iface->index;
|
||||
}
|
||||
else
|
||||
{
|
||||
ln->data = ipa_to_u32(ifa->iface->addr->ip);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ln--;
|
||||
i--; /* No link added */
|
||||
}
|
||||
|
||||
if ((ifa->state == OSPF_IS_PTP) &&
|
||||
(ptp_unnumbered_stub_lsa || !(ifa->iface->addr->flags & IA_UNNUMBERED)))
|
||||
{
|
||||
ln++;
|
||||
if (ln == ln_after)
|
||||
die("LSA space overflow");
|
||||
|
||||
ln->type = LSART_STUB;
|
||||
ln->metric = ifa->cost;
|
||||
ln->notos = 0;
|
||||
if (ifa->iface->addr->flags & IA_UNNUMBERED)
|
||||
{
|
||||
ln->id = ipa_to_u32(ifa->iface->addr->opposite);
|
||||
ln->data = 0xffffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
ln->data = ipa_to_u32(ipa_mkmask(ifa->iface->addr->pxlen));
|
||||
ln->id = ipa_to_u32(ifa->iface->addr->prefix) & ln->data;
|
||||
}
|
||||
i++;
|
||||
master = 1;
|
||||
}
|
||||
break;
|
||||
case OSPF_IT_BCAST:
|
||||
|
||||
case OSPF_IT_BCAST: /* RFC2328 - 12.4.1.2 */
|
||||
case OSPF_IT_NBMA:
|
||||
if (ifa->state == OSPF_IS_WAITING)
|
||||
{
|
||||
ln->type = LSART_STUB;
|
||||
ln->data = ipa_to_u32(ipa_mkmask(ifa->iface->addr->pxlen));
|
||||
ln->id = ipa_to_u32(ifa->iface->addr->prefix) & ln->data;
|
||||
ln->metric = ifa->cost;
|
||||
ln->notos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
|
||||
j = 0, k = 0;
|
||||
WALK_LIST(neigh, ifa->neigh_list)
|
||||
{
|
||||
|
@ -147,52 +123,64 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 * length)
|
|||
if (neigh->state == NEIGHBOR_FULL)
|
||||
j = 1;
|
||||
}
|
||||
|
||||
if (((ifa->state == OSPF_IS_DR) && (j == 1)) || (k == 1))
|
||||
{
|
||||
ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
|
||||
ln->type = LSART_NET;
|
||||
ln->id = ipa_to_u32(ifa->drip);
|
||||
ln->data = ipa_to_u32(ifa->iface->addr->ip);
|
||||
ln->metric = ifa->cost;
|
||||
ln->notos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ln->type = LSART_STUB;
|
||||
ln->data = ipa_to_u32(ipa_mkmask(ifa->iface->addr->pxlen));
|
||||
ln->id = ipa_to_u32(ifa->iface->addr->prefix) & ln->data;
|
||||
ln->metric = ifa->cost;
|
||||
ln->notos = 0;
|
||||
}
|
||||
i++;
|
||||
master = 1;
|
||||
}
|
||||
break;
|
||||
case OSPF_IT_VLINK:
|
||||
|
||||
case OSPF_IT_VLINK: /* RFC2328 - 12.4.1.3 */
|
||||
neigh = (struct ospf_neighbor *) HEAD(ifa->neigh_list);
|
||||
if ((!EMPTY_LIST(ifa->neigh_list)) && (neigh->state == NEIGHBOR_FULL) && (ifa->cost <= 0xffff))
|
||||
{
|
||||
ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
|
||||
ln->type = LSART_VLNK;
|
||||
ln->id = neigh->rid;
|
||||
ln->data = ipa_to_u32(ifa->iface->addr->ip);
|
||||
ln->metric = ifa->cost;
|
||||
ln->notos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ln--;
|
||||
i--; /* No link added */
|
||||
i++;
|
||||
master = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ln--;
|
||||
i--; /* No link added */
|
||||
log("Unknown interface type %s", ifa->iface->name);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now we will originate stub areas for interfaces addresses */
|
||||
struct ifa *a;
|
||||
WALK_LIST(a, ifa->iface->addrs)
|
||||
{
|
||||
if (((a == ifa->iface->addr) && master) ||
|
||||
(a->flags & IA_SECONDARY) ||
|
||||
(a->flags & IA_UNNUMBERED))
|
||||
continue;
|
||||
|
||||
ln = lsab_alloc(po, sizeof(struct ospf_lsa_rt_link));
|
||||
ln->type = LSART_STUB;
|
||||
ln->id = ipa_to_u32(a->prefix);
|
||||
ln->data = ipa_to_u32(ipa_mkmask(a->pxlen));
|
||||
ln->metric = ifa->cost;
|
||||
ln->notos = 0;
|
||||
i++;
|
||||
}
|
||||
ln++;
|
||||
}
|
||||
|
||||
rt = po->lsab;
|
||||
rt->links = i;
|
||||
*length = i * sizeof(struct ospf_lsa_rt_link) + sizeof(struct ospf_lsa_rt) +
|
||||
sizeof(struct ospf_lsa_header);
|
||||
return rt;
|
||||
rt->veb.bit.v = bitv;
|
||||
*length = po->lsab_used + sizeof(struct ospf_lsa_header);
|
||||
return lsab_flush(po);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue