Commit af678af0 authored by Ondřej Zajíček's avatar Ondřej Zajíček

Merge remote-tracking branch 'origin/master' into int-new

parents 286e2011 8e433d6a
Version 1.6.0 (2016-04-29)
o Major RIP protocol redesign
o New Babel routing protocol
o BGP multipath support
o KRT: Add support for plenty of kernel route metrics
o KRT: Allow more than 256 routing tables
o Static: Allow to specify attributes for static routes
o Static: Support for BFD controlled static routes
o FreeBSD: Setup password for BGP MD5 authentication
o IO: Remove socket number limit
o Plenty of bug fixes
Upgrade notes:
For RIP, most protocol options were moved to interface blocks.
Version 1.5.0 (2015-04-20)
o Major OSPF protocol redesign.
o OSPFv2 multi-instance extension (RFC 6549).
......
......@@ -37,7 +37,7 @@
#define SERVER_READ_BUF_LEN 4096
static char *opt_list = "s:vr";
static char *opt_list = "s:vrl";
static int verbose, restricted, once;
static char *init_cmd;
......@@ -59,13 +59,14 @@ int term_lns, term_cls;
static void
usage(char *name)
{
fprintf(stderr, "Usage: %s [-s <control-socket>] [-v] [-r]\n", name);
fprintf(stderr, "Usage: %s [-s <control-socket>] [-v] [-r] [-l]\n", name);
exit(1);
}
static void
parse_args(int argc, char **argv)
{
int server_changed = 0;
int c;
while ((c = getopt(argc, argv, opt_list)) >= 0)
......@@ -73,6 +74,7 @@ parse_args(int argc, char **argv)
{
case 's':
server_path = optarg;
server_changed = 1;
break;
case 'v':
verbose++;
......@@ -80,6 +82,10 @@ parse_args(int argc, char **argv)
case 'r':
restricted = 1;
break;
case 'l':
if (!server_changed)
server_path = xbasename(server_path);
break;
default:
usage(argv[0]);
}
......
......@@ -563,6 +563,7 @@ cf_lex_init_kh(void)
/**
* cf_lex_init - initialize the lexer
* @is_cli: true if we're going to parse CLI command, false for configuration
* @c: configuration structure
*
* cf_lex_init() initializes the lexical analyzer and prepares it for
* parsing of a new input.
......
......@@ -167,7 +167,7 @@ fi
AC_SUBST(iproutedir)
# all_protocols="$proto_bfd bgp ospf pipe radv rip static"
# all_protocols="$proto_bfd babel bgp ospf pipe radv rip static"
all_protocols="$proto_bfd ospf pipe radv rip static"
all_protocols=`echo $all_protocols | sed 's/ /,/g'`
......
This diff is collapsed.
......@@ -57,6 +57,9 @@ Reply codes of BIRD command-line interface
1020 Show BFD sessions
1021 Show RIP interface
1022 Show RIP neighbors
1023 Show Babel interfaces
1024 Show Babel neighbors
1025 Show Babel entries
8000 Reply too long
8001 Route not found
......
......@@ -61,6 +61,7 @@ static inline int u64_cmp(u64 i1, u64 i2)
#define NORET __attribute__((noreturn))
#define UNUSED __attribute__((unused))
#define PACKED __attribute__((packed))
/* Microsecond time */
......
......@@ -25,5 +25,6 @@ u32 u32_log2(u32 v);
static inline u32 u32_hash(u32 v) { return v * 2902958171u; }
#endif
static inline u8 u32_popcount(u32 v) { return __builtin_popcount(v); }
#endif
......@@ -26,6 +26,7 @@
#define IP6_OSPF_ALL_ROUTERS ipa_build6(0xFF020000, 0, 0, 5)
#define IP6_OSPF_DES_ROUTERS ipa_build6(0xFF020000, 0, 0, 6)
#define IP6_RIP_ROUTERS ipa_build6(0xFF020000, 0, 0, 9)
#define IP6_BABEL_ROUTERS ipa_build6(0xFF020000, 0, 0, 0x00010006)
#define IP4_NONE _MI4(0)
#define IP6_NONE _MI6(0,0,0,0)
......
......@@ -124,9 +124,10 @@ static char * number(char * str, long num, int base, int size, int precision,
* standard IP address width which depends on whether we use IPv4 or IPv6; |%I4|
* or |%I6| can be used for explicit ip4_addr / ip6_addr arguments, |%N| for
* generic network addresses (net_addr *), |%R| for Router / Network ID (u32
* value printed as IPv4 address) and |%m| resp. |%M| for error messages (uses
* strerror() to translate @errno code to message text). On the other hand, it
* doesn't support floating point numbers.
* value printed as IPv4 address), |%lR| for 64bit Router / Network ID (u64
* value printed as eight :-separated octets) and |%m| resp. |%M| for error
* messages (uses strerror() to translate @errno code to message text). On the
* other hand, it doesn't support floating point numbers.
*
* Result: number of characters of the output string or -1 if
* the buffer space was insufficient.
......@@ -137,6 +138,7 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
unsigned long num;
int i, base;
u32 x;
u64 X;
char *str, *start;
const char *s;
char ipbuf[NET_MAX_TEXT_LENGTH+1];
......@@ -338,8 +340,23 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
/* Router/Network ID - essentially IPv4 address in u32 value */
case 'R':
x = va_arg(args, u32);
ip4_ntop(ip4_from_u32(x), ipbuf);
if (qualifier == 'l') {
X = va_arg(args, u64);
bsprintf(ipbuf, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
((X >> 56) & 0xff),
((X >> 48) & 0xff),
((X >> 40) & 0xff),
((X >> 32) & 0xff),
((X >> 24) & 0xff),
((X >> 16) & 0xff),
((X >> 8) & 0xff),
(X & 0xff));
}
else
{
x = va_arg(args, u32);
ip4_ntop(ip4_from_u32(x), ipbuf);
}
s = ipbuf;
goto str;
......
......@@ -79,7 +79,7 @@ int sk_leave_group(sock *s, ip_addr maddr); /* Leave multicast group on sk iface
int sk_setup_broadcast(sock *s);
int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
int sk_set_md5_auth(sock *s, ip_addr a, struct iface *ifa, char *passwd);
int sk_set_md5_auth(sock *s, ip_addr local, ip_addr remote, struct iface *ifa, char *passwd, int setkey);
int sk_set_ipv6_checksum(sock *s, int offset);
int sk_set_icmp6_filter(sock *s, int p1, int p2);
void sk_log_error(sock *s, const char *p);
......
......@@ -24,4 +24,12 @@ void buffer_puts(buffer *buf, const char *str);
int patmatch(const byte *pat, const byte *str);
static inline char *xbasename(const char *str)
{
char *s = strrchr(str, '/');
return s ? s+1 : (char *) str;
}
#define ROUTER_ID_64_LENGTH 23
#endif
Summary: BIRD Internet Routing Daemon
Name: bird
Version: 1.5.0
Version: 1.6.0
Release: 1
Copyright: GPL
Group: Networking/Daemons
......
......@@ -357,6 +357,7 @@ dev_proto:
| dev_proto proto_item ';'
| dev_proto proto_channel ';'
| dev_proto dev_iface_patt ';'
| dev_proto CHECK LINK bool ';' { DIRECT_CFG->check_link = $4; }
;
dev_iface_init:
......
......@@ -340,7 +340,7 @@ neigh_if_link(struct iface *i)
/**
* neigh_ifa_update: notify neighbor cache about interface address add or remove event
* @ifa: interface address in question
* @a: interface address in question
*
* Tell the neighbor cache that an address was added or removed.
*
......
......@@ -148,6 +148,7 @@ void get_route_info(rte *e, byte *buf, ea_list *attrs)
* get_attr - get attribute information
* @a: an extended attribute
* @buf: buffer to be filled with attribute information
* @buflen: a length of the @buf parameter
*
* The get_attr() hook is called by the core to obtain a user friendly
* representation of an extended route attribute. It can either leave
......
......@@ -1068,6 +1068,7 @@ graceful_restart_init(void)
/**
* graceful_restart_done - finalize graceful restart
* @t: unused
*
* When there are no locks on graceful restart, the functions finalizes the
* graceful restart recovery. Protocols postponing route export until the end of
......@@ -1258,6 +1259,9 @@ protos_build(void)
proto_build(&proto_bfd);
bfd_init_all();
#endif
#ifdef CONFIG_BABEL
proto_build(&proto_babel);
#endif
proto_pool = rp_new(&root_pool, "Protocols");
proto_shutdown_timer = tm_new(proto_pool);
......
......@@ -81,7 +81,7 @@ void protos_dump_all(void);
extern struct protocol
proto_device, proto_radv, proto_rip, proto_static,
proto_ospf, proto_pipe, proto_bgp, proto_bfd;
proto_ospf, proto_pipe, proto_bgp, proto_bfd, proto_babel;
/*
* Routing Protocol Instance
......
......@@ -228,6 +228,12 @@ typedef struct rte {
struct {
u8 suppressed; /* Used for deterministic MED comparison */
} bgp;
#endif
#ifdef CONFIG_BABEL
struct {
u16 metric; /* Babel metric */
u64 router_id; /* Babel router id */
} babel;
#endif
struct { /* Routes generated by krt sync (both temporary and inherited ones) */
s8 src; /* Alleged route source (see krt.h) */
......@@ -377,6 +383,7 @@ typedef struct rta {
#define RTS_OSPF_EXT2 10 /* OSPF external route type 2 */
#define RTS_BGP 11 /* BGP route */
#define RTS_PIPE 12 /* Inter-table wormhole */
#define RTS_BABEL 13 /* Babel route */
#define RTC_UNICAST 0
#define RTC_BROADCAST 1
......@@ -425,7 +432,8 @@ typedef struct eattr {
#define EAP_RIP 2 /* RIP */
#define EAP_OSPF 3 /* OSPF */
#define EAP_KRT 4 /* Kernel route attributes */
#define EAP_MAX 5
#define EAP_BABEL 5 /* Babel attributes */
#define EAP_MAX 6
#define EA_CODE(proto,id) (((proto) << 8) | (id))
#define EA_PROTO(ea) ((ea) >> 8)
......@@ -550,6 +558,7 @@ extern struct protocol *attr_class_to_protocol[EAP_MAX];
#define DEF_PREF_DIRECT 240 /* Directly connected */
#define DEF_PREF_STATIC 200 /* Static route */
#define DEF_PREF_OSPF 150 /* OSPF intra-area, inter-area and type 1 external routes */
#define DEF_PREF_BABEL 130 /* Babel */
#define DEF_PREF_RIP 120 /* RIP */
#define DEF_PREF_BGP 100 /* BGP */
#define DEF_PREF_INHERITED 10 /* Routes inherited from other routing daemons */
......
......@@ -353,7 +353,7 @@ ea_find(ea_list *e, unsigned id)
* for first occurrences of attributes with ID in specified interval from @id to
* (@id + @max - 1), returning pointers to found &eattr structures, storing its
* walk state in @s for subsequent calls.
*
* The function ea_walk() is supposed to be called in a loop, with initially
* zeroed walk state structure @s with filled the initial extended attribute
* list, returning one found attribute in each call or %NULL when no other
......
......@@ -68,6 +68,9 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
DBG("dev_if_notify: %s:%I going up\n", ad->iface->name, ad->ip);
if (cf->check_link && !(ad->iface->flags & IF_LINK_UP))
return;
/* Use iface ID as local source ID */
struct rte_src *src = rt_get_source(P, ad->iface->index);
......@@ -87,6 +90,25 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
}
}
static void
dev_if_notify(struct proto *p, uint c, struct iface *iface)
{
struct rt_dev_config *cf = (void *) p->cf;
if (c & (IF_CHANGE_UP | IF_CHANGE_DOWN))
return;
if ((c & IF_CHANGE_LINK) && cf->check_link)
{
uint ac = (iface->flags & IF_LINK_UP) ? IF_CHANGE_UP : IF_CHANGE_DOWN;
struct ifa *a;
WALK_LIST(a, iface->addrs)
dev_ifa_notify(p, ac, a);
}
}
static struct proto *
dev_init(struct proto_config *CF)
{
......@@ -97,6 +119,7 @@ dev_init(struct proto_config *CF)
proto_configure_channel(P, &p->ip4_channel, proto_cf_find_channel(CF, NET_IP4));
proto_configure_channel(P, &p->ip6_channel, proto_cf_find_channel(CF, NET_IP6));
P->if_notify = dev_if_notify;
P->ifa_notify = dev_ifa_notify;
return P;
......@@ -109,7 +132,8 @@ dev_reconfigure(struct proto *P, struct proto_config *CF)
struct rt_dev_config *o = (void *) P->cf;
struct rt_dev_config *n = (void *) CF;
if (!iface_patts_equal(&o->iface_list, &n->iface_list, NULL))
if (!iface_patts_equal(&o->iface_list, &n->iface_list, NULL) ||
(o->check_link != n->check_link))
return 0;
return
......@@ -131,6 +155,8 @@ dev_copy_config(struct proto_config *dest, struct proto_config *src)
* old nodes cannot be modified (although they contain internal lists).
*/
cfg_copy_list(&d->iface_list, &s->iface_list, sizeof(struct iface_patt));
d->check_link = s->check_link;
}
struct protocol proto_device = {
......
......@@ -12,6 +12,7 @@
struct rt_dev_config {
struct proto_config c;
list iface_list; /* list of struct iface_patt */
int check_link;
};
struct rt_dev_proto {
......
......@@ -834,16 +834,20 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
* @net: network in question
* @new: the new route to be announced
* @old: the previous route for the same network
* @new_best: the new best route for the same network
* @old_best: the previous best route for the same network
* @before_old: The previous route before @old for the same network.
* If @before_old is NULL @old was the first.
*
* This function gets a routing table update and announces it
* to all protocols that acccepts given type of route announcement
* and are connected to the same table by their announcement hooks.
*
* Route announcement of type RA_OPTIMAL si generated when optimal
* Route announcement of type %RA_OPTIMAL si generated when optimal
* route (in routing table @tab) changes. In that case @old stores the
* old optimal route.
*
* Route announcement of type RA_ANY si generated when any route (in
* Route announcement of type %RA_ANY si generated when any route (in
* routing table @tab) changes In that case @old stores the old route
* from the same protocol.
*
......
H Protocols
C babel
C bfd
C bgp
C ospf
......
S babel.c
S packets.c
source=babel.c packets.c
root-rel=../../
dir-name=proto/babel
include ../../Rules
This diff is collapsed.
/*
* BIRD -- The Babel protocol
*
* Copyright (c) 2015--2016 Toke Hoiland-Jorgensen
*
* Can be freely distributed and used under the terms of the GNU GPL.
*
* This file contains the data structures used by Babel.
*/
#ifndef _BIRD_BABEL_H_
#define _BIRD_BABEL_H_
#include "nest/bird.h"
#include "nest/cli.h"
#include "nest/iface.h"
#include "nest/route.h"
#include "nest/protocol.h"
#include "nest/locks.h"
#include "lib/resource.h"
#include "lib/lists.h"
#include "lib/socket.h"
#include "lib/string.h"
#include "lib/timer.h"
#ifndef IPV6
#error "The Babel protocol only speaks IPv6"
#endif
#define EA_BABEL_METRIC EA_CODE(EAP_BABEL, 0)
#define EA_BABEL_ROUTER_ID EA_CODE(EAP_BABEL, 1)
#define BABEL_MAGIC 42
#define BABEL_VERSION 2
#define BABEL_PORT 6696
#define BABEL_INFINITY 0xFFFF
#define BABEL_HELLO_INTERVAL_WIRED 4 /* Default hello intervals in seconds */
#define BABEL_HELLO_INTERVAL_WIRELESS 4
#define BABEL_UPDATE_INTERVAL_FACTOR 4
#define BABEL_IHU_INTERVAL_FACTOR 3
#define BABEL_IHU_EXPIRY_FACTOR(X) ((X)*3/2) /* 1.5 */
#define BABEL_HELLO_EXPIRY_FACTOR(X) ((X)*3/2) /* 1.5 */
#define BABEL_ROUTE_EXPIRY_FACTOR(X) ((X)*7/2) /* 3.5 */
#define BABEL_ROUTE_REFRESH_INTERVAL 2 /* Seconds before route expiry to send route request */
#define BABEL_HOLD_TIME 10 /* Expiry time for our own routes */
#define BABEL_RXCOST_WIRED 96
#define BABEL_RXCOST_WIRELESS 256
#define BABEL_INITIAL_HOP_COUNT 255
#define BABEL_MAX_SEND_INTERVAL 5
#define BABEL_TIME_UNITS 100 /* On-wire times are counted in centiseconds */
#define BABEL_SEQNO_REQUEST_EXPIRY 60
#define BABEL_GARBAGE_INTERVAL 300
#define BABEL_OVERHEAD (SIZE_OF_IP_HEADER+UDP_HEADER_LENGTH)
#define BABEL_MIN_MTU (512 + BABEL_OVERHEAD)
enum babel_tlv_type {
BABEL_TLV_PAD1 = 0,
BABEL_TLV_PADN = 1,
BABEL_TLV_ACK_REQ = 2,
BABEL_TLV_ACK = 3,
BABEL_TLV_HELLO = 4,
BABEL_TLV_IHU = 5,
BABEL_TLV_ROUTER_ID = 6,
BABEL_TLV_NEXT_HOP = 7,
BABEL_TLV_UPDATE = 8,
BABEL_TLV_ROUTE_REQUEST = 9,
BABEL_TLV_SEQNO_REQUEST = 10,
/* extensions - not implemented
BABEL_TLV_TS_PC = 11,
BABEL_TLV_HMAC = 12,
BABEL_TLV_SS_UPDATE = 13,
BABEL_TLV_SS_REQUEST = 14,
BABEL_TLV_SS_SEQNO_REQUEST = 15,
*/
BABEL_TLV_MAX
};
enum babel_iface_type {
/* In practice, UNDEF and WIRED give equivalent behaviour */
BABEL_IFACE_TYPE_UNDEF = 0,
BABEL_IFACE_TYPE_WIRED = 1,
BABEL_IFACE_TYPE_WIRELESS = 2,
BABEL_IFACE_TYPE_MAX
};
enum babel_ae_type {
BABEL_AE_WILDCARD = 0,
BABEL_AE_IP4 = 1,
BABEL_AE_IP6 = 2,
BABEL_AE_IP6_LL = 3,
BABEL_AE_MAX
};
struct babel_config {
struct proto_config c;
list iface_list; /* Patterns configured -- keep it first; see babel_reconfigure why */
};
struct babel_iface_config {
struct iface_patt i;
u16 rxcost;
u8 type;
u8 check_link;
int port;
u16 hello_interval;
u16 ihu_interval;
u16 update_interval;
u16 rx_buffer; /* RX buffer size, 0 for MTU */
u16 tx_length; /* TX packet length limit (including headers), 0 for MTU */
int tx_tos;
int tx_priority;
};
struct babel_proto {
struct proto p;
timer *timer;
struct fib rtable;
list interfaces; /* Interfaces we really know about (struct babel_iface) */
u64 router_id;
u16 update_seqno; /* To be increased on request */
u8 triggered; /* For triggering global updates */
slab *route_slab;
slab *source_slab;
slab *msg_slab;
slab *seqno_slab;
list seqno_cache; /* Seqno requests in the cache (struct babel_seqno_request) */
struct tbf log_pkt_tbf; /* TBF for packet messages */
};
struct babel_iface {
node n;
struct babel_proto *proto;
struct iface *iface;
struct babel_iface_config *cf;
u8 up;
pool *pool;
char *ifname;
sock *sk;
ip_addr addr;
int tx_length;
list neigh_list; /* List of neighbors seen on this iface (struct babel_neighbor) */
list msg_queue;
u16 hello_seqno; /* To be increased on each hello */
bird_clock_t next_hello;
bird_clock_t next_regular;
bird_clock_t next_triggered;
bird_clock_t want_triggered;
timer *timer;
event *send_event;
};
struct babel_neighbor {
node n;
struct babel_iface *ifa;
ip_addr addr;
u16 txcost;
u8 hello_cnt;
u16 hello_map;
u16 next_hello_seqno;
/* expiry timers */
bird_clock_t hello_expiry;
bird_clock_t ihu_expiry;
list routes; /* Routes this neighbour has sent us (struct babel_route) */
};
struct babel_source {
node n;
u64 router_id;
u16 seqno;
u16 metric;
bird_clock_t expires;
};
struct babel_route {
node n;
node neigh_route;
struct babel_entry *e;
struct babel_neighbor *neigh;
u16 seqno;
u16 advert_metric;
u16 metric;
u64 router_id;
ip_addr next_hop;
bird_clock_t refresh_time;
bird_clock_t expires;
u16 expiry_interval;
};
struct babel_entry {
struct fib_node n;
struct babel_proto *proto;
struct babel_route *selected_in;
struct babel_route *selected_out;
bird_clock_t updated;
list sources; /* Source entries for this prefix (struct babel_source). */
list routes; /* Routes for this prefix (struct babel_route) */
};
/* Stores forwarded seqno requests for duplicate suppression. */
struct babel_seqno_request {
node n;
ip_addr prefix;
u8 plen;
u64 router_id;
u16 seqno;
bird_clock_t updated;
};
/*
* Internal TLV messages
*/
struct babel_msg_ack_req {
u8 type;
u16 nonce;
u16 interval;
ip_addr sender;
};
struct babel_msg_ack {
u8 type;
u16 nonce;
};
struct babel_msg_hello {
u8 type;
u16 seqno;
u16 interval;
ip_addr sender;
};
struct babel_msg_ihu {
u8 type;
u8 ae;
u16 rxcost;
u16 interval;
ip_addr addr;
ip_addr sender;
};
struct babel_msg_update {
u8 type;
u8 ae;
u8 plen;
u16 interval;
u16 seqno;
u16 metric;
ip_addr prefix;
u64 router_id;
ip_addr next_hop;
ip_addr sender;
};
struct babel_msg_route_request {
u8 type;
u8 full;
u8 plen;
ip_addr prefix;
};
struct babel_msg_seqno_request {
u8 type;
u8 plen;
u16 seqno;
u8 hop_count;
u64 router_id;
ip_addr prefix;
ip_addr sender;
};
union babel_msg {
u8 type;
struct babel_msg_ack_req ack_req;
struct babel_msg_ack ack;
struct babel_msg_hello hello;
struct babel_msg_ihu ihu;
struct babel_msg_update update;
struct babel_msg_route_request route_request;
struct babel_msg_seqno_request seqno_request;
};
struct babel_msg_node {
node n;
union babel_msg msg;
};
/* babel.c */
void babel_handle_ack_req(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_ack(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_hello(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_ihu(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_router_id(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_update(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_route_request(union babel_msg *msg, struct babel_iface *ifa);
void babel_handle_seqno_request(union babel_msg *msg, struct babel_iface *ifa);
void babel_show_interfaces(struct proto *P, char *iff);
void babel_show_neighbors(struct proto *P, char *iff);
void babel_show_entries(struct proto *P);
/* packets.c */
void babel_enqueue(union babel_msg *msg, struct babel_iface *ifa);
void babel_send_unicast(union babel_msg *msg, struct babel_iface *ifa, ip_addr dest);
int babel_open_socket(struct babel_iface *ifa);
void babel_send_queue(void *arg);
#endif
/*
* BIRD -- Babel Configuration
*