Bird now uses fib structure instead of linklist.
This commit is contained in:
parent
1d7c44b711
commit
6996f459c6
3 changed files with 96 additions and 142 deletions
|
@ -4,6 +4,14 @@
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
To add:
|
||||||
|
|
||||||
|
passive option (== do not send routing updates to this interface)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CF_HDR
|
CF_HDR
|
||||||
|
|
||||||
#include "proto/rip/rip.h"
|
#include "proto/rip/rip.h"
|
||||||
|
|
164
proto/rip/rip.c
164
proto/rip/rip.c
|
@ -31,73 +31,6 @@ rip_reply(struct proto *p)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Entries
|
|
||||||
*/
|
|
||||||
|
|
||||||
static struct rip_entry *
|
|
||||||
new_entry( struct proto *p )
|
|
||||||
{
|
|
||||||
struct rip_entry *e;
|
|
||||||
e = mb_alloc(p->pool, sizeof( struct rip_entry ));
|
|
||||||
bzero( e, sizeof( struct rip_entry ));
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct rip_entry *
|
|
||||||
find_entry( struct proto *p, ip_addr network, int pxlen )
|
|
||||||
{
|
|
||||||
struct node *e;
|
|
||||||
|
|
||||||
CHK_MAGIC;
|
|
||||||
WALK_LIST( e, P->rtable ) {
|
|
||||||
if (ipa_equal( network, E->network ) &&
|
|
||||||
(pxlen == E->pxlen)) {
|
|
||||||
return E;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete one of entries */
|
|
||||||
static void
|
|
||||||
kill_entry_ourrt( struct proto *p, struct rip_entry *e )
|
|
||||||
{
|
|
||||||
struct rip_connection *c;
|
|
||||||
net *n;
|
|
||||||
|
|
||||||
rem_node( NODE e );
|
|
||||||
WALK_LIST( c, P->connections ) {
|
|
||||||
if (c->sendptr == e) {
|
|
||||||
DBG( "Deleting from under someone's sendptr...\n" );
|
|
||||||
c->sendptr = (void *) (NODE c->sendptr)->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mb_free( e );
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Currently unreferenced, and likely may stay that way */
|
|
||||||
/* Delete one of entries */
|
|
||||||
static void
|
|
||||||
kill_entry_mainrt( struct proto *p, struct rip_entry *e )
|
|
||||||
{
|
|
||||||
struct rip_connection *c;
|
|
||||||
net *n;
|
|
||||||
|
|
||||||
n = net_find(&master_table, 0, e->network, e->pxlen );
|
|
||||||
if (!n) log( L_ERR "Could not find entry to delete in main routing table." );
|
|
||||||
else rte_update( n, p, NULL );
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
kill_entry( struct proto *p, struct rip_entry *e )
|
|
||||||
{
|
|
||||||
kill_entry_mainrt( p, e );
|
|
||||||
kill_entry_ourrt( p, e );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Output processing
|
* Output processing
|
||||||
*/
|
*/
|
||||||
|
@ -117,13 +50,11 @@ rip_tx( sock *s )
|
||||||
struct rip_connection *c = rif->busy;
|
struct rip_connection *c = rif->busy;
|
||||||
struct proto *p = c->proto;
|
struct proto *p = c->proto;
|
||||||
struct rip_packet *packet = (void *) s->tbuf;
|
struct rip_packet *packet = (void *) s->tbuf;
|
||||||
int i, done = 0;
|
int i;
|
||||||
|
|
||||||
givemore:
|
do {
|
||||||
|
|
||||||
DBG( "Preparing packet to send: " );
|
if (c->done) {
|
||||||
|
|
||||||
if (!(NODE c->sendptr)->next) {
|
|
||||||
DBG( "Looks like I'm" );
|
DBG( "Looks like I'm" );
|
||||||
c->rif->busy = NULL;
|
c->rif->busy = NULL;
|
||||||
rem_node(NODE c);
|
rem_node(NODE c);
|
||||||
|
@ -132,21 +63,28 @@ givemore:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (c->done) {
|
||||||
|
DBG( "looks like I'm done!\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG( "Preparing packet to send: " );
|
||||||
|
|
||||||
packet->heading.command = RIPCMD_RESPONSE;
|
packet->heading.command = RIPCMD_RESPONSE;
|
||||||
packet->heading.version = RIP_V2;
|
packet->heading.version = RIP_V2;
|
||||||
packet->heading.unused = 0;
|
packet->heading.unused = 0;
|
||||||
|
|
||||||
for (i = 0; i < 25; i++) {
|
i = 0;
|
||||||
if (!(NODE c->sendptr)->next)
|
FIB_ITERATE_START(&P->rtable, &c->iter, z) {
|
||||||
break;
|
struct rip_entry *e = (struct rip_entry *) z;
|
||||||
DBG( "." );
|
DBG( "." );
|
||||||
packet->block[i].family = htons( 2 ); /* AF_INET */
|
packet->block[i].family = htons( 2 ); /* AF_INET */
|
||||||
packet->block[i].tag = htons( 0 ); /* FIXME: What should I set it to? */
|
packet->block[i].tag = htons( 0 ); /* FIXME: What should I set it to? */
|
||||||
packet->block[i].network = c->sendptr->network;
|
packet->block[i].network = e->n.prefix;
|
||||||
packet->block[i].netmask = ipa_mkmask( c->sendptr->pxlen );
|
packet->block[i].netmask = ipa_mkmask( e->n.pxlen );
|
||||||
packet->block[i].nexthop = IPA_NONE; /* FIXME: How should I set it? */
|
packet->block[i].nexthop = IPA_NONE; /* FIXME: How should I set it? */
|
||||||
packet->block[i].metric = htonl( 1+ (c->sendptr->metric?:1) );
|
packet->block[i].metric = htonl( 1+ (e->metric?:1) );
|
||||||
if (ipa_equal(c->sendptr->whotoldme, s->daddr)) {
|
if (ipa_equal(e->whotoldme, s->daddr)) {
|
||||||
DBG( "(split horizont)" );
|
DBG( "(split horizont)" );
|
||||||
/* FIXME: should we do it in all cases? */
|
/* FIXME: should we do it in all cases? */
|
||||||
packet->block[i].metric = P->infinity;
|
packet->block[i].metric = P->infinity;
|
||||||
|
@ -155,8 +93,14 @@ givemore:
|
||||||
ipa_hton( packet->block[i].netmask );
|
ipa_hton( packet->block[i].netmask );
|
||||||
ipa_hton( packet->block[i].nexthop );
|
ipa_hton( packet->block[i].nexthop );
|
||||||
|
|
||||||
c->sendptr = (void *) (NODE c->sendptr)->next;
|
if (i++ == 25) {
|
||||||
|
FIB_ITERATE_PUT(&c->iter, z);
|
||||||
|
goto break_loop;
|
||||||
}
|
}
|
||||||
|
} FIB_ITERATE_END;
|
||||||
|
c->done = 1;
|
||||||
|
|
||||||
|
break_loop:
|
||||||
|
|
||||||
DBG( ", sending %d blocks, ", i );
|
DBG( ", sending %d blocks, ", i );
|
||||||
|
|
||||||
|
@ -164,12 +108,12 @@ givemore:
|
||||||
i = sk_send_to( s, sizeof( struct rip_packet_heading ) + i*sizeof( struct rip_block ), c->daddr, c->dport );
|
i = sk_send_to( s, sizeof( struct rip_packet_heading ) + i*sizeof( struct rip_block ), c->daddr, c->dport );
|
||||||
else
|
else
|
||||||
i = sk_send( s, sizeof( struct rip_packet_heading ) + i*sizeof( struct rip_block ) );
|
i = sk_send( s, sizeof( struct rip_packet_heading ) + i*sizeof( struct rip_block ) );
|
||||||
if (i<0) rip_tx_err( s, i );
|
|
||||||
if (i>0) {
|
|
||||||
DBG( "it wants more\n" );
|
|
||||||
goto givemore;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
DBG( "it wants more\n" );
|
||||||
|
|
||||||
|
} while (i>0);
|
||||||
|
|
||||||
|
if (i<0) rip_tx_err( s, i );
|
||||||
DBG( "blocked\n" );
|
DBG( "blocked\n" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +146,8 @@ rip_sendto( struct proto *p, ip_addr daddr, int dport, struct rip_interface *rif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
c->sendptr = HEAD( P->rtable );
|
c->done = 0;
|
||||||
|
fit_init( &c->iter, &P->rtable );
|
||||||
add_head( &P->connections, NODE c );
|
add_head( &P->connections, NODE c );
|
||||||
debug( "Sending my routing table to %I:%d on %s\n", daddr, dport, rif->iface->name );
|
debug( "Sending my routing table to %I:%d on %s\n", daddr, dport, rif->iface->name );
|
||||||
|
|
||||||
|
@ -385,7 +330,7 @@ static void
|
||||||
rip_dump_entry( struct rip_entry *e )
|
rip_dump_entry( struct rip_entry *e )
|
||||||
{
|
{
|
||||||
debug( "%I told me %d/%d ago: to %I/%d go via %I, metric %d ",
|
debug( "%I told me %d/%d ago: to %I/%d go via %I, metric %d ",
|
||||||
e->whotoldme, e->updated-now, e->changed-now, e->network, e->pxlen, e->nexthop, e->metric );
|
e->whotoldme, e->updated-now, e->changed-now, e->n.prefix, e->n.pxlen, e->nexthop, e->metric );
|
||||||
if (e->flags & RIP_F_EXTERNAL) debug( "[external]" );
|
if (e->flags & RIP_F_EXTERNAL) debug( "[external]" );
|
||||||
debug( "\n" );
|
debug( "\n" );
|
||||||
}
|
}
|
||||||
|
@ -412,15 +357,16 @@ rip_timer(timer *t)
|
||||||
|
|
||||||
DBG( "RIP: Broadcasting routing tables\n" );
|
DBG( "RIP: Broadcasting routing tables\n" );
|
||||||
{
|
{
|
||||||
struct rip_interface *i;
|
struct rip_interface *rif;
|
||||||
|
|
||||||
WALK_LIST( i, P->interfaces ) {
|
WALK_LIST( rif, P->interfaces ) {
|
||||||
struct iface *iface = i->iface;
|
struct iface *iface = rif->iface;
|
||||||
|
|
||||||
|
if (!iface) continue;
|
||||||
if (!(iface->flags & IF_UP)) continue;
|
if (!(iface->flags & IF_UP)) continue;
|
||||||
if (iface->flags & (IF_IGNORE | IF_LOOPBACK)) continue;
|
if (iface->flags & (IF_IGNORE | IF_LOOPBACK)) continue;
|
||||||
|
|
||||||
rip_sendto( p, IPA_NONE, 0, i );
|
rip_sendto( p, IPA_NONE, 0, rif );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,10 +376,11 @@ rip_timer(timer *t)
|
||||||
static void
|
static void
|
||||||
rip_start(struct proto *p)
|
rip_start(struct proto *p)
|
||||||
{
|
{
|
||||||
|
struct rip_interface *rif;
|
||||||
DBG( "RIP: starting instance...\n" );
|
DBG( "RIP: starting instance...\n" );
|
||||||
|
|
||||||
P->magic = RIP_MAGIC;
|
P->magic = RIP_MAGIC;
|
||||||
init_list( &P->rtable );
|
fib_init( &P->rtable, p->pool, sizeof( struct rip_entry ), 0, NULL );
|
||||||
init_list( &P->connections );
|
init_list( &P->connections );
|
||||||
init_list( &P->garbage );
|
init_list( &P->garbage );
|
||||||
init_list( &P->interfaces );
|
init_list( &P->interfaces );
|
||||||
|
@ -443,6 +390,8 @@ rip_start(struct proto *p)
|
||||||
P->timer->recurrent = P->period;
|
P->timer->recurrent = P->period;
|
||||||
P->timer->hook = rip_timer;
|
P->timer->hook = rip_timer;
|
||||||
tm_start( P->timer, 5 );
|
tm_start( P->timer, 5 );
|
||||||
|
rif = new_iface(p, NULL, 0); /* Initialize dummy interface */
|
||||||
|
add_head( &P->interfaces, NODE rif );
|
||||||
CHK_MAGIC;
|
CHK_MAGIC;
|
||||||
|
|
||||||
DBG( "RIP: ...done\n");
|
DBG( "RIP: ...done\n");
|
||||||
|
@ -466,10 +415,10 @@ rip_dump(struct proto *p)
|
||||||
debug( "RIP: connection #%d: %I\n", n->num, n->addr );
|
debug( "RIP: connection #%d: %I\n", n->num, n->addr );
|
||||||
}
|
}
|
||||||
i = 0;
|
i = 0;
|
||||||
WALK_LIST( e, P->rtable ) {
|
FIB_WALK( &P->rtable, e ) {
|
||||||
debug( "RIP: entry #%d: ", i++ );
|
debug( "RIP: entry #%d: ", i++ );
|
||||||
rip_dump_entry( E );
|
rip_dump_entry( E );
|
||||||
}
|
} FIB_WALK_END;
|
||||||
i = 0;
|
i = 0;
|
||||||
WALK_LIST( rif, P->interfaces ) {
|
WALK_LIST( rif, P->interfaces ) {
|
||||||
debug( "RIP: interface #%d: %s, %I, busy = %x\n", i++, rif->iface?rif->iface->name:"(dummy)", rif->sock->daddr, rif->busy );
|
debug( "RIP: interface #%d: %s, %I, busy = %x\n", i++, rif->iface?rif->iface->name:"(dummy)", rif->sock->daddr, rif->busy );
|
||||||
|
@ -502,6 +451,7 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags)
|
||||||
rif = mb_alloc(p->pool, sizeof( struct rip_interface ));
|
rif = mb_alloc(p->pool, sizeof( struct rip_interface ));
|
||||||
rif->iface = new;
|
rif->iface = new;
|
||||||
rif->proto = p;
|
rif->proto = p;
|
||||||
|
rif->busy = NULL;
|
||||||
|
|
||||||
want_multicast = 0 && (flags & IF_MULTICAST);
|
want_multicast = 0 && (flags & IF_MULTICAST);
|
||||||
/* FIXME: should have config option to disable this one */
|
/* FIXME: should have config option to disable this one */
|
||||||
|
@ -512,7 +462,7 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags)
|
||||||
rif->sock->rx_hook = rip_rx;
|
rif->sock->rx_hook = rip_rx;
|
||||||
rif->sock->data = rif;
|
rif->sock->data = rif;
|
||||||
rif->sock->rbsize = 10240;
|
rif->sock->rbsize = 10240;
|
||||||
rif->sock->iface = new;
|
rif->sock->iface = new; /* Automagically works for dummy interface */
|
||||||
rif->sock->tbuf = mb_alloc( p->pool, sizeof( struct rip_packet ));
|
rif->sock->tbuf = mb_alloc( p->pool, sizeof( struct rip_packet ));
|
||||||
rif->sock->tx_hook = rip_tx;
|
rif->sock->tx_hook = rip_tx;
|
||||||
rif->sock->err_hook = rip_tx_err;
|
rif->sock->err_hook = rip_tx_err;
|
||||||
|
@ -528,10 +478,10 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags)
|
||||||
rif->sock->daddr = new->opposite;
|
rif->sock->daddr = new->opposite;
|
||||||
|
|
||||||
if (!ipa_nonzero(rif->sock->daddr))
|
if (!ipa_nonzero(rif->sock->daddr))
|
||||||
log( L_WARN "RIP: interface %s is too strange for me", rif->iface->name );
|
log( L_WARN "RIP: interface %s is too strange for me", rif->iface ? rif->iface->name : "(dummy)" );
|
||||||
|
|
||||||
if (sk_open(rif->sock)<0)
|
if (sk_open(rif->sock)<0)
|
||||||
die( "RIP/%s: could not listen on %s", p->name, rif->iface->name );
|
die( "RIP/%s: could not listen on %s", p->name, rif->iface ? rif->iface->name : "(dummy)" );
|
||||||
/* FIXME: Should not be fatal, since the interface might have gone */
|
/* FIXME: Should not be fatal, since the interface might have gone */
|
||||||
|
|
||||||
return rif;
|
return rif;
|
||||||
|
@ -567,27 +517,24 @@ rip_rt_notify(struct proto *p, struct network *net, struct rte *new, struct rte
|
||||||
CHK_MAGIC;
|
CHK_MAGIC;
|
||||||
|
|
||||||
if (old) {
|
if (old) {
|
||||||
struct rip_entry *e = find_entry( p, net->n.prefix, net->n.pxlen );
|
struct rip_entry *e = fib_find( &P->rtable, &net->n.prefix, net->n.pxlen );
|
||||||
|
|
||||||
if (!e)
|
if (!e)
|
||||||
log( L_ERR "Deleting nonexistent entry?!" );
|
log( L_BUG "Deleting nonexistent entry?!" );
|
||||||
|
fib_delete( &P->rtable, e );
|
||||||
kill_entry_ourrt( p, e );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new) {
|
if (new) {
|
||||||
struct rip_entry *e = new_entry( p );
|
struct rip_entry *e;
|
||||||
|
if (fib_find( &P->rtable, &net->n.prefix, net->n.pxlen ))
|
||||||
|
log( L_BUG "Inserting entry which is already there?" );
|
||||||
|
e = fib_get( &P->rtable, &net->n.prefix, net->n.pxlen );
|
||||||
|
|
||||||
e->network = net->n.prefix;
|
|
||||||
e->pxlen = net->n.pxlen;
|
|
||||||
e->nexthop = new->attrs->gw;
|
e->nexthop = new->attrs->gw;
|
||||||
e->tag = new->u.rip.tag;
|
e->tag = new->u.rip.tag;
|
||||||
e->metric = new->u.rip.metric;
|
e->metric = new->u.rip.metric;
|
||||||
e->whotoldme = new->attrs->from;
|
e->whotoldme = new->attrs->from;
|
||||||
e->updated = e->changed = now;
|
e->updated = e->changed = now;
|
||||||
e->flags = 0;
|
e->flags = 0;
|
||||||
|
|
||||||
add_head( &P->rtable, NODE e );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -658,9 +605,6 @@ rip_preconfig(struct protocol *x)
|
||||||
static void
|
static void
|
||||||
rip_postconfig(struct protocol *p)
|
rip_postconfig(struct protocol *p)
|
||||||
{
|
{
|
||||||
#if 0 /* Cannot do this since it crashes when RIP is unconfigured */
|
|
||||||
new_iface(p, NULL, 0);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct protocol proto_rip = {
|
struct protocol proto_rip = {
|
||||||
|
|
|
@ -2,18 +2,21 @@
|
||||||
* Structures for RIP protocol
|
* Structures for RIP protocol
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "nest/route.h"
|
||||||
|
|
||||||
struct rip_connection {
|
struct rip_connection {
|
||||||
node n;
|
node n;
|
||||||
|
|
||||||
int num;
|
int num;
|
||||||
struct proto *proto;
|
struct proto *proto;
|
||||||
ip_addr addr;
|
ip_addr addr;
|
||||||
struct rip_entry *sendptr;
|
|
||||||
sock *send;
|
sock *send;
|
||||||
struct rip_interface *rif;
|
struct rip_interface *rif;
|
||||||
|
struct fib_iterator iter;
|
||||||
|
|
||||||
ip_addr daddr;
|
ip_addr daddr;
|
||||||
int dport;
|
int dport;
|
||||||
|
int done;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rip_packet_heading {
|
struct rip_packet_heading {
|
||||||
|
@ -39,11 +42,9 @@ struct rip_block {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rip_entry {
|
struct rip_entry {
|
||||||
node n;
|
struct fib_node n;
|
||||||
|
|
||||||
ip_addr whotoldme;
|
ip_addr whotoldme;
|
||||||
ip_addr network;
|
|
||||||
int pxlen;
|
|
||||||
ip_addr nexthop;
|
ip_addr nexthop;
|
||||||
int metric;
|
int metric;
|
||||||
u16 tag;
|
u16 tag;
|
||||||
|
@ -72,7 +73,7 @@ struct rip_proto {
|
||||||
struct proto inherited;
|
struct proto inherited;
|
||||||
timer *timer;
|
timer *timer;
|
||||||
list connections;
|
list connections;
|
||||||
list rtable;
|
struct fib rtable;
|
||||||
list garbage;
|
list garbage;
|
||||||
list interfaces; /* Interfaces we really know about */
|
list interfaces; /* Interfaces we really know about */
|
||||||
list iface_list; /* Patterns configured */
|
list iface_list; /* Patterns configured */
|
||||||
|
@ -91,3 +92,4 @@ struct rip_proto {
|
||||||
#define CHK_MAGIC do { if (P->magic != RIP_MAGIC) bug( "Not enough magic\n" ); } while (0)
|
#define CHK_MAGIC do { if (P->magic != RIP_MAGIC) bug( "Not enough magic\n" ); } while (0)
|
||||||
|
|
||||||
void rip_init_instance(struct proto *p);
|
void rip_init_instance(struct proto *p);
|
||||||
|
struct rip_interface *new_iface(struct proto *p, struct iface *new, unsigned long flags);
|
||||||
|
|
Loading…
Reference in a new issue