Commit 58ef912c authored by Martin Mareš's avatar Martin Mareš

First look at data structures. More to come tomorrow...

parent b60f7489
# Makefile for the BIRD Internet Routing Daemon
# (c) 1998 Martin Mares <mj@ucw.cz>
TOPDIR=$(shell pwd)
CFLAGS=-O2 -Wall -W -Wstrict-prototypes -Wno-unused -Wno-parentheses -I$(TOPDIR)
PROTOCOLS=
DIRS=sysdep/linux nest $(protocols) lib
ARCHS=$(join $(addsuffix /,$(DIRS)),$(subst /,_,$(addsuffix .a,$(DIRS))))
export
all: all-dirs bird
all-dirs:
set -e ; for a in $(DIRS) ; do $(MAKE) -C $$a ; done
bird: $(ARCHS)
$(CC) $(LDFLAGS) -o $@ $^
clean:
rm -f `find . -name "*~" -or -name "*.[oa]" -or -name "\#*\#" -or -name TAGS -or -name core`
rm -f bird
# Makefile for the BIRD Internet Routing Daemon
# (c) 1998 Martin Mares <mj@ucw.cz>
THISDIR=$(shell pwd)
RELDIR=$(subst $(TOPDIR)/,,$(THISDIR))
ANAME=$(subst /,_,$(RELDIR)).a
all: $(ANAME)
$(ANAME): $(OBJS)
rm -f $(ANAME)
ar rcs $(ANAME) $(OBJS)
Core
~~~~
- route validation
- fake multipath?
- config file: symbolic constants?
- counters (according to SNMP MIB?)
- generation of subnet mask ICMP's for v6?
- debugging dumps and protocol tracing!
- unaligned accesses?
RIP
~~~
- RIP: export-only and import-only mode?
- drop RIPv1 (Historic protocol)?
OSPF
~~~~
Almquist & Kastenholz [Page 111]
RFC 1716 Towards Requirements for IP Routers November 1994
7.2.2.2 Specific Issues
Virtual Links
There is a minor error in the specification that can cause
routing loops when all of the following conditions are
simultaneously true:
(1) A virtual link is configured through a transit area,
(2) Two separate paths exist, each having the same
endpoints, but one utilizing only non-virtual
backbone links, and the other using links in the
transit area, and
(3) The latter path is part of the (underlying physical
representation of the) configured virtual link,
routing loops may occur.
To prevent this, an implementation of OSPF SHOULD invoke
the calculation in Section 16.3 of [ROUTE:1] whenever any
part of the path to the destination is a virtual link (the
specification only says this is necessary when the first
hop is a virtual link).
BGP
~~~
- BGP:
- in, local, out RIB
- maxsize=4096
- BGP identifier aka router id
- removal of loops
- aggregation, ATOMIC_AGGREGATE
- communities
- confederations
- attributes must be sorted!
- re-export of NEXT_HOP attribute
- BGP session over currently down interface
- route flap dampening?
- LOCAL_PREF attribute
- error notification received -> log error
- set TTL to 1 (configurable?)
- consulting IGP for next-hop information? (what if it changes?)
- inter-advertisement delay???!
- normalize (sort) incoming AS-SET's
- maximum length of AS paths
- expected neighbor AS
- hold time
- idle timer after error: initial value, exponential growth, maximum value
- address testing macros (ALL_ZEROS)
- all internal tables are in network order (?)
- logging of errors and debug dumps
- filter: logging of dropped routes (?)
- limitation of memory consumption: per-process and total
- alloca
- precedence of all packets (incl. TCP)
- adding of route: clear all bits not covered by masklen
- switch: generate default route only if at least one BGP connection exists
- route update: new, change, remove
- route recalculation timing
- CONFIG_TOS
- CONFIG_MULTIPATH
- reconfiguration without restart of all protocols?
- change of interface address: ??? (down and up?)
- "generate default route" switch for all IGP's
- RIPv2:
- Route Tag
- limit routing table xfer (frequency, only to neighbors)
- multicast on/off
- remember routes for all neighbors?
- BGP:
- import of IGP routes (use external route tags from OSPF)
- Interface:
- RIP metric
- multicast capability flag
- MTU
- OSPF metrics (per-TOS)
- running protocol on an interface:
- interface is not required to exist
- can specify a wildcard pattern or an interface list
- preferences:
- directly connected
- static
- OSPF internal, OSPF ext type 1 (comparable metrics), OSPF inter-area
- RIP
- BGP
- OSPF ext type 2
- sink
- lib:
- MD5
- OSPF:
- Dijkstra: use Fibonacci heaps?
- point-to-point interface with address: advertise as stub network
- static routes: stub networks?
- modes: PtP, PtP-unnumbered, Broadcast, NBMA, point-to-multipoint
- importing of device routes for networks where we don't run OSPF
- tie breaking for equal type 2 ext metrics by using internal (type 1) metric
- SPF tree recalc timing (per-area timers?)
- aggregation: specify network list for each area
- stub area: either no external routes or only default route
- automatic generation of external route tags (RFC1403) -- what about
using the same rule for RIPv2? [shared code?]
- timers - one-shot and periodic, resolution 1 sec, randomized
- re-configuration: restart of routing protocols (shutdown mode)
- route: originating AS
- Check incoming packets and log errors!!
OBJS=lists.o
include $(TOPDIR)/Rules
/*
* BIRD Library
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_BIRDLIB_H_
#define _BIRD_BIRDLIB_H_
/* Ugly structure offset handling macros */
#define OFFSETOF(s, i) ((unsigned int)&((s *)0)->i)
#define SKIP_BACK(s, i, p) ((s *)((char *)p - OFFSETOF(s, i)))
#endif
/*
* BIRD Library -- Linked Lists
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#define _BIRD_LISTS_C_
#include <nest/bird.h>
#include <lib/lists.h>
LIST_INLINE void
add_tail(list *l, node *n)
{
node *z = l->tail;
n->next = (node *) &l->tail;
n->prev = z;
z->next = n;
l->tail = n;
}
LIST_INLINE void
add_head(list *l, node *n)
{
node *z = l->head;
n->next = z;
n->prev = (node *) &l->head;
z->prev = n;
l->head = n;
}
LIST_INLINE void
insert_node(node *n, node *after)
{
node *z = after->next;
n->next = z;
n->prev = after;
after->next = n;
z->prev = n;
}
LIST_INLINE void
rem_node(node *n)
{
node *z = n->prev;
node *x = n->next;
z->next = x;
x->prev = z;
}
LIST_INLINE void
init_list(list *l)
{
l->head = (node *) &l->null;
l->null = NULL;
l->tail = (node *) &l->head;
}
LIST_INLINE void
add_tail_list(list *to, list *l)
{
node *p = to->tail;
node *q = l->head;
p->next = q;
q->prev = p;
q = l->tail;
q->next = (node *) &to->null;
to->tail = q;
}
/*
* BIRD Library -- Linked Lists
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_LISTS_H_
#define _BIRD_LISTS_H_
typedef struct node {
struct node *next, *prev;
} node;
typedef struct list { /* In fact two overlayed nodes */
struct node *head, *null, *tail;
} list;
#define NODE (node *)
#define HEAD(list) ((void *)((list).head))
#define TAIL(list) ((void *)((list).tail))
#define WALK_LIST(n,list) for((n)=HEAD(list);(NODE (n))->next; \
n=(void *)((NODE (n))->next))
#define EMPTY_LIST(list) (!(list).head->next)
void add_tail(list *, node *);
void add_head(list *, node *);
void rem_node(node *);
void add_tail_list(list *, list *);
void init_list(list *);
void insert_node(node *, node *);
#ifndef _BIRD_LISTS_C_
#define LIST_INLINE extern inline
#include <lib/lists.c>
#undef LIST_INLINE
#else
#define LIST_INLINE
#endif
#endif
/*
* BIRD Resource Manager
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_RESOURCE_H_
#define _BIRD_RESOURCE_H_
#include <lib/lists.h>
/* Resource */
typedef struct resource {
node n; /* Inside resource pool */
struct resclass *class; /* Resource class */
} resource;
/* Resource class */
struct resclass {
char *name; /* Resource class name */
unsigned size; /* Standard size of single resource */
void (*free)(resource *); /* Freeing function */
void (*dump)(resource *); /* Dump to debug output */
};
/* Generic resource manipulation */
typedef struct pool pool;
pool *rp_new(pool *); /* Create new pool */
void rp_init(pool *); /* Initialize static pool */
void rp_empty(pool *); /* Free everything in the pool */
void rfree(void *); /* Free single resource */
void rdump(void *); /* Dump to debug output */
void ralloc(pool *, struct resclass *);
/* Normal memory blocks */
void *mb_alloc(pool *, unsigned size);
void *mb_free(void *);
/* Memory pools with linear allocation */
typedef struct mempool mempool;
mempool *mp_new(pool *, unsigned blk);
void mp_trim(pool *); /* Free unused memory */
void *mp_alloc(mempool *, unsigned size); /* Aligned */
void *mp_allocu(mempool *, unsigned size); /* Unaligned */
void *mp_allocz(mempool *, unsigned size); /* With clear */
/* Slabs */
typedef struct slab slab;
slab *sl_new(pool *, unsigned size);
void *sl_alloc(slab *);
void sl_free(slab *, void *);
/* Low-level memory allocation functions, please don't use */
void *xmalloc(unsigned);
#define xfree(x) free(x)
#endif
/*
* BIRD Socket Interface
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_SOCKET_H_
#define _BIRD_SOCKET_H_
#include <lib/resource.h>
typedef struct birdsock socket;
#endif
/*
* BIRD Timers
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_TIMER_H_
#define _BIRD_TIMER_H_
#include <lib/resource.h>
typedef struct timer {
resource r;
void (*hook)(struct timer *);
void *data;
/* internal fields should be here */
} timer;
timer *tm_new(pool *, void (*hook)(timer *), void *data);
void tm_start(timer *, unsigned after);
void tm_stop(timer *);
void tm_trigger(timer *);
#endif
/*
* Unaligned Data Accesses
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_UNALIGNED_H_
#define _BIRD_UNALIGNED_H_
#endif
OBJS=main.o
include $(TOPDIR)/Rules
/*
* BIRD Internet Routing Daemon -- Basic Declarations
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_BIRD_H_
#define _BIRD_BIRD_H_
#include <sysdep/config.h>
#include <lib/birdlib.h>
#ifndef IPV6
#include <nest/ipv4.h>
#else
#include <nest/ipv6.h>
#endif
extern u32 router_id; /* Our Router ID */
extern u16 this_as; /* Our Autonomous System Number */
#endif
/*
* BIRD Internet Routing Daemon -- Configuration File
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_CONFILE_H_
#define _BIRD_CONFILE_H_
#endif
/*
* BIRD Internet Routing Daemon -- Network Interfaces
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_IFACE_H_
#define _BIRD_IFACE_H_
#endif
/*
* BIRD -- IP Addresses et Cetera for IPv4
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_IPV4_H_
#define _BIRD_IPV4_H_
#include <netinet/in.h>
typedef struct ipv4_addr {
u32 addr;
} ip_addr;
#define ipa_equal(x,y) ((x).addr == (y).addr)
#endif
/*
* BIRD -- IP Addresses et Cetera for IPv6
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_IPV4_H_
#define _BIRD_IPV4_H_
#include <netinet/in.h>
#include <string.h>
typedef struct ipv4_addr {
u32 addr[4];
} ip_addr;
#define ipa_equal(x,y) (!memcmp(&(x),&(y),sizeof(ip_addr)))
#endif
/*
* BIRD Internet Routing Daemon
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include <nest/bird.h>
#include <lib/lists.h>
#include <nest/resource.h>
int
main(void)
{
ip_addr x,y;
x=y;
if (ipa_equal(x,y)) return 1;
return 0;
}
/*
* BIRD Internet Routing Daemon -- Protocols
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_PROTOCOL_H_
#define _BIRD_PROTOCOL_H_
#include <lib/resource.h>
/*
* Routing Protocol
*/
struct protocol {
char *name;
unsigned type; /* ??? List values ??? */
unsigned debug; /* Default debugging flags */
void (*init)(struct protocol *); /* Boot time */
void (*preconfig)(struct protocol *); /* Just before configuring */
void (*postconfig)(struct protocol *); /* After configuring */
};
void protos_init(void);
void protos_preconfig(void);
void protos_postconfig(void);
/*
* Known protocols
*/
extern struct protocol proto_static;
/*
* Routing Protocol Instance
*/
struct proto {
struct proto *next;
struct protocol *proto; /* Protocol */
char *name; /* Name of this instance */
unsigned debug; /* Debugging flags */
pool *pool; /* Local objects */
unsigned preference; /* Default route preference */
void (*if_notify)(struct proto *, struct iface *old, struct iface *new);
void (*rt_notify)(struct proto *, struct rte *old, struct rte *new);
void (*debug)(struct proto *); /* Debugging dump */
void (*start)(struct proto *); /* Start the instance */
void (*shutdown)(struct proto *, int time); /* Stop the instance */
/* Reconfigure function? */
/* Interface patterns */
/* Input/output filters */
/* Connection to routing tables? */
/* Hic sunt protocol-specific data */
};
void *proto_new(struct protocol *, unsigned size);
#endif
/*
* BIRD Internet Routing Daemon -- Routing Table
*
* (c) 1998 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_ROUTE_H_
#define _BIRD_ROUTE_H_
#include <lib/resource.h>
/*
* Generic data structure for storing network prefixes. Also used
* for the master routing table. Currently implemented as a radix
* trie.
*
* Available operations:
* - insertion of new entry
* - deletion of entry
* - searching of entry by network prefix
* - searching of entry by IP address (longest match)
*/
struct fib_node {
ip_addr prefix; /* In host order */
byte pxlen;
byte flags; /* ??? define them ??? */
byte pad0, pad1; /* ??? use ??? */
struct fib_node *left, *right, *up; /* Radix Trie links */
};
struct fib {
slab fib_slab; /* Slab holding all fib nodes */
struct fib_node root;
void (*init)(struct fib_node *); /* Constructor */
};
void fib_init(struct fib *, pool *, unsigned node_size, void (*init)(struct fib_node *));
void *fib_find(struct fib *, ip_addr *, int); /* Find or return NULL if doesn't exist */
void *fib_find_ip(struct fib *, ip_addr *); /* Longest match (always exists) */
void *fib_get(struct fib *, ip_addr *, int); /* Find or create new if nonexistent */
void fib_delete(struct fib *);
/*
* Master Routing Table. Generally speaking, it's a FIB with each entry
* pointing to a list of route entries representing routes to given network.
* Each of the RTE's contains variable data (the preference and protocol-dependent
* metrics) and a pointer to route attribute block common for many routes).
*/
typedef struct network {
struct fib_node n;
struct rte *routes; /* Available routes for this network */
struct network *next; /* Next in Recalc Chain */
} net;
typedef struct rte {
struct rte *next;
struct rtattr *attrs;
byte flags; /* Flags (REF_...) */
byte rfu;
word pref; /* Route preference */
union { /* Protocol-dependent data (metrics etc.) */
#ifdef CONFIG_STATIC
struct {
} stat;
#endif
#ifdef CONFIG_RIP
struct {
byte metric; /* RIP metric */
} rip;
#endif
#ifdef CONFIG_OSPF
struct {
u32 metric1, metric2; /* OSPF Type 1 and Type 2 metrics */
} ospf;
#endif
#ifdef CONFIG_BGP
struct {
} bgp;
#endif
} u;
} rte;
#define REF_CHOSEN 1 /* Currently chosen route */
typedef struct rte rte;
/*
* Route Attributes
*
* Beware: All standard BGP attributes must be represented here instead
* of making them local to the route. This is needed to ensure proper
* construction of BGP route attribute lists.
*/
struct rtattr {
struct rtattr *next, *prev; /* Hash chain */
struct rtattr *garbage; /* Garbage collector chain */
struct proto *proto; /* Protocol instance */
unsigned uc; /* Use count */
byte source; /* Route source (RTS_...) */
byte scope; /* Route scope (SCOPE_...) */
byte cast; /* Casting type (RTC_...) */
byte dest; /* Route destination type (RTD_...) */
byte tos; /* TOS of this route */
byte flags; /* Route flags (RTF_...) */
word source_as; /* Source AS of this route (0=local) */
ip_addr gw; /* Next hop */
struct iface *iface; /* Outgoing interface */
struct ea_list *attrs; /* Extended Attribute chain */
} rta;
#define RTS_STATIC 1 /* Normal static route */
#define RTS_INHERIT 2 /* Route inherited from kernel */
#define RTS_DEVICE 3 /* Device route */
#define RTS_STATIC_DEVICE 4 /* Static device route */
#define RTS_REDIRECT 5 /* Learned via redirect */
#define RTS_RIP 6 /* RIP route */
#define RTS_RIP_EXT 7 /* RIP external route */
#define RTS_OSPF 8 /* OSPF route */
#define RTS_OSPF_EXT 9 /* OSPF external route */
#define RTS_OSPF_IA 10 /* OSPF inter-area route */
#define RTS_OSPF_BOUNDARY 11 /* OSPF route to boundary router */
#define RTS_BGP 12 /* BGP route */
#define SCOPE_HOST 0 /* Address scope */
#define SCOPE_LINK 0x10
#define SCOPE_SITE 0x80
#define SCOPE_UNIVERSE 0xff
#define RTC_UNICAST 0
#define RTC_BROADCAST 1
#define RTC_MULTICAST 2
#define RTC_ANYCAST 3 /* IPv6 Anycast */
#define RTD_ROUTER 0 /* Next hop is neighbor router */
#define RTD_DEVICE 1 /* Points to device */
#define RTD_BLACKHOLE 2 /* Silently drop packets */
#define RTD_UNREACHABLE 3 /* Reject as unreachable */
#define RTD_PROHIBIT 4 /* Administratively prohibited */