Changes OSPF to generate stub networks for non-primary addresses.

Also does some reorganization in RT LSA announcement.
This commit is contained in:
Ondrej Zajicek 2009-06-10 23:45:08 +02:00
parent b99d378698
commit 3d15dcdb1c
6 changed files with 184 additions and 109 deletions

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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)
{

View file

@ -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);

View file

@ -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);
}
/**