Triggered updates should now actually work. Fixed metric=16 -> time it
out logic.
This commit is contained in:
parent
774f149959
commit
7e61cac325
3 changed files with 62 additions and 96 deletions
55
bird.conf
55
bird.conf
|
@ -8,61 +8,6 @@ router id 62.168.0.1;
|
||||||
|
|
||||||
define xyzzy = 120+10;
|
define xyzzy = 120+10;
|
||||||
|
|
||||||
function callme ( int arg1; int arg2 )
|
|
||||||
int local1;
|
|
||||||
int local2;
|
|
||||||
int i;
|
|
||||||
{
|
|
||||||
print "Function callme called arguments " arg1 " and " arg2;
|
|
||||||
i = arg2;
|
|
||||||
|
|
||||||
case arg1 {
|
|
||||||
2: print "dva"; print "jeste jednou dva";
|
|
||||||
3 .. 5: print "tri az pet";
|
|
||||||
else: print "neco jineho";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function startup ()
|
|
||||||
int i;
|
|
||||||
prefix px;
|
|
||||||
ip p;
|
|
||||||
{
|
|
||||||
print "Testing filter language:";
|
|
||||||
i = 4;
|
|
||||||
i = 1230 + i;
|
|
||||||
i = ( i + 0 );
|
|
||||||
print " arithmetics: 1234 = " i;
|
|
||||||
printn " if statements ";
|
|
||||||
if i = 4 then { print "*** FAIL: if 0"; quitbird; } else printn ".";
|
|
||||||
if 1234 = i then printn "."; else { print "*** FAIL: if 1 else"; }
|
|
||||||
if 1 <= 1 then printn "."; else { print "*** FAIL: test 3"; }
|
|
||||||
if 1234 < 1234 then { print "*** FAIL: test 4"; quitbird; } else print "ok";
|
|
||||||
print " data types; must be true: " 1.2.3.4 = 1.2.3.4 "," 1 ~ [1,2,3] "," 5 ~ [1..20] "," 2 ~ [ 1, 2, 3 ] "," 5 ~ [ 4 .. 7 ] "," 1.2.3.4 ~ [ 1.2.3.3..1.2.3.5 ] "," 1.2.3.4 ~ 1.2.3.4/8 "," 1.2.3.4/8 ~ 1.2.3.4/8 "," 1.2.3.4/8 ~ [ 1.2.3.4/8+ ] "," 1.2.3.4/16 ~ [ 1.2.3.4/8{ 15 , 16 } ] "," defined(1) "," defined(1.2.3.4);
|
|
||||||
print " data types: must be false: " 1 ~ [ 2, 3, 4 ] "," 5 ~ [ 2, 3, 4, 7..11 ] "," 1.2.3.4 ~ [ 1.2.3.3, 1.2.3.5 ] "," (1,2) > (2,2) "," (1,1) > (1,1) "," 1.2.3.4/8 ~ [ 1.2.3.4/8- ] "," 1.2.3.4/17 ~ [ 1.2.3.4/8{ 15 , 16 } ];
|
|
||||||
|
|
||||||
px = 1.2.3.4/18;
|
|
||||||
print "Testing prefixes: 1.2.3.4/18 = " px;
|
|
||||||
p = 127.1.2.3;
|
|
||||||
print "Testing mask : 127.0.0.0 = " p.mask(8);
|
|
||||||
print "Testing pairs: (1,2) = " (1,2);
|
|
||||||
print "Set of enums: " RTSDUMMY;
|
|
||||||
|
|
||||||
print "What will this do? " [ 1, 2, 1, 1, 1, 3, 4, 1, 1, 1, 5 ];
|
|
||||||
|
|
||||||
print "Testing functions...";
|
|
||||||
# callme ( 1, 2 );
|
|
||||||
callme ( 2, 2 );
|
|
||||||
callme ( 2, 2 );
|
|
||||||
callme ( 3, 2 );
|
|
||||||
callme ( 4, 2 );
|
|
||||||
callme ( 7, 2 );
|
|
||||||
|
|
||||||
print "done";
|
|
||||||
quitbird;
|
|
||||||
# print "*** FAIL: this is unreachable";
|
|
||||||
}
|
|
||||||
|
|
||||||
filter testf
|
filter testf
|
||||||
int j;
|
int j;
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,15 +8,18 @@
|
||||||
FIXME: IpV6 support: packet size
|
FIXME: IpV6 support: packet size
|
||||||
FIXME: IpV6 support: use right address for broadcasts
|
FIXME: IpV6 support: use right address for broadcasts
|
||||||
FIXME: IpV6 support: receive "route using" blocks
|
FIXME: IpV6 support: receive "route using" blocks
|
||||||
FIXME: Do we send "triggered updates" correctly? No.
|
|
||||||
FIXME: When route's metric changes to 16, start garbage collection immediately? Do _not_ restart on new updates with metric == 16.
|
FIXME: fold rip_connection into rip_interface?
|
||||||
FIXME: When route's 60 seconds old and we get same metric, use that!
|
|
||||||
FIXME: Triggered updates. When triggered update was sent, don't send new one for something between 1 and 5 seconds (and send one after that).
|
|
||||||
|
|
||||||
We are not going to honour requests for sending part of
|
We are not going to honour requests for sending part of
|
||||||
routing table. That would need to turn split horizont off,
|
routing table. That would need to turn split horizont off,
|
||||||
etc.
|
etc.
|
||||||
|
|
||||||
|
Triggered updates. When triggered update was sent, don't send
|
||||||
|
new one for something between 1 and 5 seconds (and send one
|
||||||
|
after that), says RFC. We do something else: once in 5 second
|
||||||
|
we look for any changed routes and broadcast them.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LOCAL_DEBUG
|
#define LOCAL_DEBUG
|
||||||
|
@ -64,6 +67,46 @@ rip_tx_err( sock *s, int err )
|
||||||
log( L_ERR "Unexpected error at rip transmit: %m" );
|
log( L_ERR "Unexpected error at rip transmit: %m" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rip_tx_prepare(struct proto *p, ip_addr daddr, struct rip_block *b, struct rip_entry *e )
|
||||||
|
{
|
||||||
|
DBG( "." );
|
||||||
|
b->family = htons( 2 ); /* AF_INET */
|
||||||
|
b->tag = htons( e->tag );
|
||||||
|
b->network = e->n.prefix;
|
||||||
|
#ifndef IPV6
|
||||||
|
b->netmask = ipa_mkmask( e->n.pxlen );
|
||||||
|
ipa_hton( b->netmask );
|
||||||
|
b->nexthop = IPA_NONE;
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* FIXME: This DOESN'T work. The s->daddr will be typically
|
||||||
|
* a broadcast or multicast address which will be of course
|
||||||
|
* rejected by the neighbor cache. I've #ifdef'd out the whole
|
||||||
|
* test to avoid dereferencing NULL pointer. --mj
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
neighbor *n1, *n2;
|
||||||
|
n1 = neigh_find( p, &daddr, 0 ); /* FIXME, mj: this is neccessary for responses, still it is too complicated for common case */
|
||||||
|
n2 = neigh_find( p, &e->nexthop, 0 );
|
||||||
|
if (n1->iface == n2->iface)
|
||||||
|
b->nexthop = e->nexthop;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
b->nexthop = IPA_NONE;
|
||||||
|
}
|
||||||
|
ipa_hton( b->nexthop );
|
||||||
|
#else
|
||||||
|
b->pxlen = e->n.pxlen;
|
||||||
|
#endif
|
||||||
|
b->metric = htonl( e->metric );
|
||||||
|
if (ipa_equal(e->whotoldme, daddr)) { /* FIXME: ouch, daddr is some kind of broadcast address. How am I expected to do split horizont?!?!? */
|
||||||
|
DBG( "(split horizont)" );
|
||||||
|
b->metric = P_CF->infinity;
|
||||||
|
}
|
||||||
|
ipa_hton( b->network );
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rip_tx( sock *s )
|
rip_tx( sock *s )
|
||||||
{
|
{
|
||||||
|
@ -94,42 +137,11 @@ rip_tx( sock *s )
|
||||||
i = !!P_CF->authtype;
|
i = !!P_CF->authtype;
|
||||||
FIB_ITERATE_START(&P->rtable, &c->iter, z) {
|
FIB_ITERATE_START(&P->rtable, &c->iter, z) {
|
||||||
struct rip_entry *e = (struct rip_entry *) z;
|
struct rip_entry *e = (struct rip_entry *) z;
|
||||||
DBG( "." );
|
|
||||||
packet->block[i].family = htons( 2 ); /* AF_INET */
|
|
||||||
packet->block[i].tag = htons( e->tag );
|
|
||||||
packet->block[i].network = e->n.prefix;
|
|
||||||
#ifndef IPV6
|
|
||||||
packet->block[i].netmask = ipa_mkmask( e->n.pxlen );
|
|
||||||
ipa_hton( packet->block[i].netmask );
|
|
||||||
packet->block[i].nexthop = IPA_NONE;
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* FIXME: This DOESN'T work. The s->daddr will be typically
|
|
||||||
* a broadcast or multicast address which will be of course
|
|
||||||
* rejected by the neighbor cache. I've #ifdef'd out the whole
|
|
||||||
* test to avoid dereferencing NULL pointer. --mj
|
|
||||||
*/
|
|
||||||
#if 0
|
|
||||||
neighbor *n1, *n2;
|
|
||||||
n1 = neigh_find( p, &s->daddr, 0 ); /* FIXME, mj: this is neccessary for responses, still it is too complicated for common case */
|
|
||||||
n2 = neigh_find( p, &e->nexthop, 0 );
|
|
||||||
if (n1->iface == n2->iface)
|
|
||||||
packet->block[i].nexthop = e->nexthop;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
packet->block[i].nexthop = IPA_NONE;
|
|
||||||
}
|
|
||||||
ipa_hton( packet->block[i].nexthop );
|
|
||||||
#else
|
|
||||||
packet->block[i].pxlen = e->n.pxlen;
|
|
||||||
#endif
|
|
||||||
packet->block[i].metric = htonl( e->metric );
|
|
||||||
if (ipa_equal(e->whotoldme, s->daddr)) {
|
|
||||||
DBG( "(split horizont)" );
|
|
||||||
packet->block[i].metric = P_CF->infinity;
|
|
||||||
}
|
|
||||||
ipa_hton( packet->block[i].network );
|
|
||||||
|
|
||||||
|
if (rif->triggered && (!(e->updated < now-5)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
rip_tx_prepare( p, s->daddr, packet->block + i, e );
|
||||||
if (i++ == ((P_CF->authtype == AT_MD5) ? PACKET_MD5_MAX : PACKET_MAX)) {
|
if (i++ == ((P_CF->authtype == AT_MD5) ? PACKET_MD5_MAX : PACKET_MAX)) {
|
||||||
FIB_ITERATE_PUT(&c->iter, z);
|
FIB_ITERATE_PUT(&c->iter, z);
|
||||||
goto break_loop;
|
goto break_loop;
|
||||||
|
@ -143,6 +155,8 @@ rip_tx( sock *s )
|
||||||
rip_outgoing_authentication(p, (void *) &packet->block[0], packet, i);
|
rip_outgoing_authentication(p, (void *) &packet->block[0], packet, i);
|
||||||
|
|
||||||
DBG( ", sending %d blocks, ", i );
|
DBG( ", sending %d blocks, ", i );
|
||||||
|
if (!i)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (ipa_nonzero(c->daddr))
|
if (ipa_nonzero(c->daddr))
|
||||||
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 );
|
||||||
|
@ -155,6 +169,8 @@ rip_tx( sock *s )
|
||||||
|
|
||||||
if (i<0) rip_tx_err( s, i );
|
if (i<0) rip_tx_err( s, i );
|
||||||
DBG( "blocked\n" );
|
DBG( "blocked\n" );
|
||||||
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -166,6 +182,7 @@ rip_sendto( struct proto *p, ip_addr daddr, int dport, struct rip_interface *rif
|
||||||
|
|
||||||
if (rif->busy) {
|
if (rif->busy) {
|
||||||
log (L_WARN "Interface %s is much too slow, dropping request", iface->name);
|
log (L_WARN "Interface %s is much too slow, dropping request", iface->name);
|
||||||
|
/* FIXME: memory leak */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rif->busy = c;
|
rif->busy = c;
|
||||||
|
@ -424,6 +441,7 @@ rip_timer(timer *t)
|
||||||
DBG( "RIP: Broadcasting routing tables\n" );
|
DBG( "RIP: Broadcasting routing tables\n" );
|
||||||
{
|
{
|
||||||
struct rip_interface *rif;
|
struct rip_interface *rif;
|
||||||
|
P->tx_count ++;
|
||||||
|
|
||||||
WALK_LIST( rif, P->interfaces ) {
|
WALK_LIST( rif, P->interfaces ) {
|
||||||
struct iface *iface = rif->iface;
|
struct iface *iface = rif->iface;
|
||||||
|
@ -432,6 +450,7 @@ rip_timer(timer *t)
|
||||||
if (rif->patt->mode & IM_QUIET) continue;
|
if (rif->patt->mode & IM_QUIET) continue;
|
||||||
if (!(iface->flags & IF_UP)) continue;
|
if (!(iface->flags & IF_UP)) continue;
|
||||||
|
|
||||||
|
rif->triggered = (P->tx_count % 6);
|
||||||
rip_sendto( p, IPA_NONE, 0, rif );
|
rip_sendto( p, IPA_NONE, 0, rif );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -694,7 +713,7 @@ rip_rte_better(struct rte *new, struct rte *old)
|
||||||
if (old->u.rip.metric > new->u.rip.metric)
|
if (old->u.rip.metric > new->u.rip.metric)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (new->u.rip.metric == 16) {
|
if ((old->u.rip.metric != 16) && (new->u.rip.metric == 16)) {
|
||||||
struct proto *p = new->attrs->proto;
|
struct proto *p = new->attrs->proto;
|
||||||
new->u.rip.lastmodX = now - P_CF->timeout_time; /* Check this: if new metric is 16, act as it was timed out */
|
new->u.rip.lastmodX = now - P_CF->timeout_time; /* Check this: if new metric is 16, act as it was timed out */
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,7 @@ struct rip_interface {
|
||||||
sock *sock;
|
sock *sock;
|
||||||
struct rip_connection *busy;
|
struct rip_connection *busy;
|
||||||
struct rip_patt *patt;
|
struct rip_patt *patt;
|
||||||
|
int triggered;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rip_patt {
|
struct rip_patt {
|
||||||
|
@ -144,6 +145,7 @@ struct rip_proto {
|
||||||
list garbage;
|
list garbage;
|
||||||
list interfaces; /* Interfaces we really know about */
|
list interfaces; /* Interfaces we really know about */
|
||||||
int magic;
|
int magic;
|
||||||
|
int tx_count; /* Do one regular update once in a while */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue