Commit c609d039 authored by Jan Moskyto Matejka's avatar Jan Moskyto Matejka

Merge branch 'int-new' into nexthop-merged

parents 62e64905 2be9218a
Version 2.0.0-pre0 (2016-12-07)
o Integrated IPv4 + IPv6 design
o Major BGP protocol redesign
o BGP multicast support (SAFI 2)
o BGP flowspec support (RFC 5575)
o New RPKI-Router protocol
o New build system
o Unit tests
Notes:
Protocols and tables are now connected using explicit channels, most related
protocol options (table, import, export, ...) are now channel options. See
doc/bird.conf.example2 for configuration examples.
Version 1.6.3 (2016-12-21)
o Large BGP communities
o BFD authentication (MD5, SHA1)
o SHA1 and SHA2 authentication for RIP and OSPF
o Improved documentation
o Several bug fixes
Version 1.6.2 (2016-09-29)
o Fixes serious bug introduced in the previous version
......
......@@ -186,8 +186,7 @@ fi
AC_SUBST(iproutedir)
# all_protocols="$proto_bfd babel bgp ospf pipe radv rip $proto_rpki static"
all_protocols="$proto_bfd bgp ospf pipe radv rip $proto_rpki static "
all_protocols="$proto_bfd babel bgp ospf pipe radv rip $proto_rpki static"
all_protocols=`echo $all_protocols | sed 's/ /,/g'`
......
/*
* This is an example configuration file.
* This is an example configuration file
* (for version 1.x.x, obsolete)
*/
# Yes, even shell-like comments work...
......
/*
* This is an example configuration file for MB-BGP setting
*/
log "bird.log" all;
# debug protocols all;
router id 192.168.1.1;
ipv4 table master4;
ipv6 table master6;
ipv4 table mcast4;
ipv6 table mcast6;
flow4 table flowtab4;
flow6 table flowtab6;
protocol device {
scan time 10;
}
protocol kernel kernel4 {
scan time 20;
ipv4 {
export all;
};
}
protocol kernel kernel6 {
scan time 20;
ipv6 {
export all;
};
}
protocol static static4 {
ipv4;
route 10.10.0.0/24 via 192.168.1.2;
route 10.10.1.0/24 via 192.168.1.2 { bgp_large_community.add((10,20,30)); bgp_large_community.add((10,(20*3),10)); };
}
protocol static static6 {
ipv6;
route 2001:db8:10:10::/64 via 2001:db8:1:1::10;
route 2001:db8:10:11::/64 via 2001:db8:1:1::10;
route 2001:db8:1:1::/64 via fe80::ec9b:67ff:fe60:fd5d % ve1;
}
# RFC 5575 flow specification
protocol static flowstat4 {
flow4;
route flow4 {
dst 10.0.0.0/8;
proto = 23;
dport > 24 && < 30 || 40..50,60..70,80;
sport > 24 && < 30 || = 40 || 50,60..70,80;
icmp type 80;
icmp code 90;
tcp flags 0x03/0x0f;
length 2048..65535;
dscp = 63;
fragment dont_fragment, is_fragment || !first_fragment;
} drop;
route flow4 {
dst 11.0.0.0/8;
proto = 0x12;
sport > 0x5678 && < 0x9abc || 0xdef0 || 0x1234,0x5678,0x9abc..0xdef0;
dport = 50;
tcp flags 0xabcd/0xbbdd;
} drop;
route flow4 {
dst 12.0.0.0/32;
tcp flags ! 0 / 0x9999;
} drop;
route flow4 {
dst 220.0.254.0/24;
tcp flags 0x99 / 0x9999;
} drop;
route flow4 {
dst 220.0.254.192/28;
tcp flags !0xffff / 0xFFFF;
} drop;
route flow4 {
dst 15.0.0.0/8;
tcp flags !0x9999/0x9999;
} drop;
}
protocol static flowstat6 {
flow6;
route flow6 {
dst fec0:1122:3344:5566::1/128;
src 0000:0000:0000:0001:1234:5678:9800:0000/101 offset 63;
next header = 23;
sport 24..30, 42 || 50,60,70..80;
dport = 50;
tcp flags 0x03/0x0f, !0/0xff || 0x33/0x33;
fragment !is_fragment || !first_fragment;
label 0xaaaa/0xaaaa && 0x33/0x33;
} drop;
route flow6 {
dst fec0:1122:3344:5566::1/128;
src ::1:1234:5678:9800:0/101 offset 63;
next header = 23;
dport = 50;
sport > 24 && < 30 || = 40 || = 50 || = 60 || >= 70 && <= 80;
tcp flags 0x3/0x3 && 0x0/0xc;
} drop;
}
protocol pipe {
table master4;
peer table mcast4;
import none;
export where source = RTS_OSPF;
}
protocol pipe {
table master6;
peer table mcast6;
import none;
export where source = RTS_OSPF;
}
protocol ospf2 ospf4 {
# ecmp;
ipv4 {
import all;
# export where source = RTS_STATIC;
};
area 0 {
interface "ve0" { stub; };
interface "ve1" { hello 5; type ptp; };
interface "ve2" { hello 5; type bcast; ttl security; };
interface "ve3" { hello 5; type bcast; ttl security; };
};
}
protocol ospf3 ospf6 {
# ecmp;
ipv6 {
import all;
# export where source = RTS_STATIC;
};
area 0 {
interface "ve0" { stub; };
interface "ve1" { hello 5; type ptp; };
interface "ve2" { hello 5; type bcast; };
};
}
protocol bgp {
local 192.168.11.1 as 1000;
neighbor 192.168.11.2 as 2000;
# local 192.168.1.1 as 1000;
# neighbor 192.168.2.1 as 2000;
# multihop;
# rr client;
# strict bind;
# debug all;
# regular IPv4 unicast (1/1)
ipv4 {
# connects to master4 table by default
import all;
export where source ~ [ RTS_STATIC, RTS_BGP ];
};
# regular IPv6 unicast (2/1)
ipv6 {
# connects to master6 table by default
import all;
export where source ~ [ RTS_STATIC, RTS_BGP ];
# next hop address 2001:db8:1:1::1;
};
# IPv4 multicast topology (1/2)
ipv4 multicast {
# explicit IPv4 table
table mcast4;
import all;
export all;
};
# IPv6 multicast topology (2/2)
ipv6 multicast {
# explicit IPv6 table
table mcast6;
import all;
export all;
# next hop address 2001:db8:1:1::1;
};
# IPv4 Flowspec (1/133)
flow4 {
# connects to flowtab4 table by default
import all;
export all;
};
# IPv6 Flowspec (2/133)
flow6 {
# connects to flowtab6 table by default
import all;
export all;
};
}
protocol bgp {
local 192.168.1.1 as 1000;
neighbor 192.168.3.1 as 1000;
multihop;
rr client;
ipv4 {
import all;
export where source ~ [ RTS_STATIC, RTS_BGP ];
};
ipv6 {
import all;
export where source ~ [ RTS_STATIC, RTS_BGP ];
next hop address 2001:db8:1:1::1;
};
}
protocol bgp {
local 2001:db8:1:1::1 as 1000;
neighbor 2001:db8:4:1::1 as 1000;
multihop;
rr client;
ipv4 {
import all;
export where source ~ [ RTS_STATIC, RTS_BGP ];
next hop address 192.168.4.1;
};
ipv6 {
import all;
export where source ~ [ RTS_STATIC, RTS_BGP ];
};
}
......@@ -1945,12 +1945,11 @@ avoid routing loops.
<p>BIRD supports all requirements of the BGP4 standard as defined in
<rfc id="4271"> It also supports the community attributes (<rfc id="1997">),
capability negotiation (<rfc id="5492">), MD5 password authentication (<rfc
id="2385">), extended communities (<rfc id="4360">), route reflectors (<rfc
id="4456">), graceful restart (<rfc id="4724">), multiprotocol extensions
(<rfc id="4760">), 4B AS numbers (<rfc id="4893">), and 4B AS numbers in
extended communities (<rfc id="5668">).
capability negotiation (<rfc id="5492">), MD5 password authentication
(<rfc id="2385">), extended communities (<rfc id="4360">), route reflectors
(<rfc id="4456">), AS confederations (<rfc id="5065">), graceful restart
(<rfc id="4724">), multiprotocol extensions (<rfc id="4760">), 4B AS numbers
(<rfc id="4893">), and 4B AS numbers in extended communities (<rfc id="5668">).
For IPv6, it uses the standard multiprotocol extensions defined in
<rfc id="4760"> and applied to IPv6 according to <rfc id="2545">.
......@@ -2041,6 +2040,16 @@ using the following configuration parameters:
source address for the BGP session. Default: the address of the local
end of the interface our neighbor is connected to.
<tag><label id="bgp-strict-bind">strict bind <m/switch/</tag>
Specify whether BGP listening socket should be bound to a specific local
address (the same as the <cf/source address/) and associated interface,
or to all addresses. Binding to a specific address could be useful in
cases like running multiple BIRD instances on a machine, each using its
IP address. Note that listening sockets bound to a specific address and
to all addresses collide, therefore either all BGP protocols (of the
same address family and using the same local port) should have set
<cf/strict bind/, or none of them. Default: disabled.
<tag><label id="bgp-next-hop-self">next hop self</tag>
Avoid calculation of the Next Hop attribute and always advertise our own
source address as a next hop. This needs to be used only occasionally to
......@@ -2113,7 +2122,7 @@ using the following configuration parameters:
Note that full (ICMP protection, for example) <rfc id="5082"> support is
provided by Linux only. Default: disabled.
<tag><label id="bgp-pass">password <m/string/</tag>
<tag><label id="bgp-password">password <m/string/</tag>
Use this password for MD5 authentication of BGP sessions (<rfc id="2385">). When
used on BSD systems, see also <cf/setkey/ option below. Default: no
authentication.
......@@ -2134,6 +2143,21 @@ using the following configuration parameters:
accepting incoming connections. In passive mode, outgoing connections
are not initiated. Default: off.
<tag><label id="bgp-confederation">confederation <m/number/</tag>
BGP confederations (<rfc id="5065">) are collections of autonomous
systems that act as one entity to external systems, represented by one
confederation identifier (instead of AS numbers). This option allows to
enable BGP confederation behavior and to specify the local confederation
identifier. When BGP confederations are used, all BGP speakers that are
members of the BGP confederation should have the same confederation
identifier configured. Default: 0 (no confederation).
<tag><label id="bgp-confederation-member">confederation member <m/switch/</tag>
When BGP confederations are used, this option allows to specify whether
the BGP neighbor is a member of the same confederation as the local BGP
speaker. The option is unnecessary (and ignored) for IBGP sessions, as
the same AS number implies the same confederation. Default: no.
<tag><label id="bgp-rr-client">rr client</tag>
Be a route reflector and treat the neighbor as a route reflection
client. Default: disabled.
......@@ -2256,13 +2280,6 @@ using the following configuration parameters:
This option is relevant to IPv4 mode with enabled capability
advertisement only. Default: on.
<tag><label id="bgp-route-limit">route limit <m/number/</tag>
The maximal number of routes that may be imported from the protocol. If
the route limit is exceeded, the connection is closed with an error.
Limit is currently implemented as <cf>import limit <m/number/ action
restart</cf>. This option is obsolete and it is replaced by
<ref id="proto-import-limit" name="import limit option">. Default: no limit.
<tag><label id="bgp-disable-after-error">disable after error <m/switch/</tag>
When an error is encountered (either locally or by the other side),
disable the instance automatically and wait for an administrator to fix
......
......@@ -1578,6 +1578,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
case P('<','='): TWOARGS; break;
case '!': ONEARG; break;
case P('!', '~'):
case '~': TWOARGS; break;
case P('d','e'): ONEARG; break;
......
......@@ -957,7 +957,7 @@ fragment_val_str(u8 val)
return "???";
}
static int
static uint
net_format_flow(char *buf, uint blen, const byte *data, uint dlen, int ipv6)
{
buffer b = {
......@@ -1125,7 +1125,7 @@ net_format_flow(char *buf, uint blen, const byte *data, uint dlen, int ipv6)
* of written chars. If final string is too large, the string will ends the with
* ' ...}' sequence and zero-terminator.
*/
int
uint
flow4_net_format(char *buf, uint blen, const net_addr_flow4 *f)
{
return net_format_flow(buf, blen, f->data, f->length - sizeof(net_addr_flow4), 0);
......@@ -1141,7 +1141,7 @@ flow4_net_format(char *buf, uint blen, const net_addr_flow4 *f)
* of written chars. If final string is too large, the string will ends the with
* ' ...}' sequence and zero-terminator.
*/
int
uint
flow6_net_format(char *buf, uint blen, const net_addr_flow6 *f)
{
return net_format_flow(buf, blen, f->data, f->length - sizeof(net_addr_flow6), 1);
......
......@@ -42,6 +42,9 @@ const char *flow_type_str(enum flow_type type, int ipv6);
uint flow_write_length(byte *data, u16 len);
static inline u16 flow_hdr_length(const byte *data)
{ return ((*data & 0xf0) == 0xf0) ? 2 : 1; }
static inline u16 flow_read_length(const byte *data)
{ return ((*data & 0xf0) == 0xf0) ? get_u16(data) & 0x0fff : *data; }
......@@ -128,7 +131,7 @@ void flow6_validate_cf(net_addr_flow6 *f);
* Net Formatting
*/
int flow4_net_format(char *buf, uint blen, const net_addr_flow4 *f);
int flow6_net_format(char *buf, uint blen, const net_addr_flow6 *f);
uint flow4_net_format(char *buf, uint blen, const net_addr_flow4 *f);
uint flow6_net_format(char *buf, uint blen, const net_addr_flow6 *f);
#endif /* _BIRD_FLOWSPEC_H_ */
......@@ -30,20 +30,17 @@ t_read_length(void)
{
byte data[] = { 0xcc, 0xcc, 0xcc };
u16 get;
u16 expect;
for (uint expect = 0; expect < 0xf0; expect++)
{
*data = expect;
get = flow_read_length(data);
uint get = flow_read_length(data);
bt_assert_msg(get == expect, "Testing get length 0x%02x (get 0x%02x)", expect, get);
}
for (uint expect = 0; expect <= 0xfff; expect++)
{
put_u16(data, expect | 0xf000);
get = flow_read_length(data);
uint get = flow_read_length(data);
bt_assert_msg(get == expect, "Testing get length 0x%03x (get 0x%03x)", expect, get);
}
......@@ -54,12 +51,10 @@ static int
t_write_length(void)
{
byte data[] = { 0xcc, 0xcc, 0xcc };
uint offset;
byte *c;
for (uint expect = 0; expect <= 0xfff; expect++)
{
offset = flow_write_length(data, expect);
uint offset = flow_write_length(data, expect);
uint set = (expect < 0xf0) ? *data : (get_u16(data) & 0x0fff);
bt_assert_msg(set == expect, "Testing set length 0x%03x (set 0x%03x)", expect, set);
......
......@@ -25,6 +25,12 @@
(v).data = mb_allocz(pool, HASH_SIZE(v) * sizeof(* (v).data)); \
})
#define HASH_FREE(v) \
({ \
mb_free((v).data); \
(v) = (typeof(v)){ }; \
})
#define HASH_FIND(v,id,key...) \
({ \
u32 _h = HASH_FN(v, id, key); \
......
Summary: BIRD Internet Routing Daemon
Name: bird
Version: 1.6.2
Version: 2.0.0
Release: 1
Copyright: GPL
Group: Networking/Daemons
......
......@@ -25,7 +25,7 @@
#define BAD(DSC, VAL) ({ err_dsc = DSC; err_val = VAL; goto bad; })
int
as_path_valid(byte *data, uint len, int bs, char *err, uint elen)
as_path_valid(byte *data, uint len, int bs, int confed, char *err, uint elen)
{
byte *pos = data;
char *err_dsc = NULL;
......@@ -43,9 +43,21 @@ as_path_valid(byte *data, uint len, int bs, char *err, uint elen)
if (len < slen)
BAD("segment framing error", len);
/* XXXX handle CONFED segments */
if ((type != AS_PATH_SET) && (type != AS_PATH_SEQUENCE))
switch (type)
{
case AS_PATH_SET:
case AS_PATH_SEQUENCE:
break;
case AS_PATH_CONFED_SEQUENCE:
case AS_PATH_CONFED_SET:
if (!confed)
BAD("AS_CONFED* segment", type);
break;
default:
BAD("unknown segment", type);
}
if (pos[1] == 0)
BAD("zero-length segment", type);
......@@ -157,10 +169,13 @@ as_path_contains_confed(const struct adata *path)
return 0;
}
static void
as_path_strip_confed_(byte *dst, const byte *src, uint len)
struct adata *
as_path_strip_confed(struct linpool *pool, const struct adata *path)
{
const byte *end = src + len;
struct adata *res = lp_alloc_adata(pool, path->length);
const byte *src = path->data;
const byte *end = src + path->length;
byte *dst = res->data;
while (src < end)
{
......@@ -176,18 +191,15 @@ as_path_strip_confed_(byte *dst, const byte *src, uint len)
src += slen;
}
}
struct adata *
as_path_strip_confed(struct linpool *pool, const struct adata *op)
{
struct adata *np = lp_alloc_adata(pool, op->length);
as_path_strip_confed_(np->data, op->data, op->length);
return np;
/* Fix the result length */
res->length = dst - res->data;
return res;
}
struct adata *
as_path_prepend2(struct linpool *pool, const struct adata *op, int seq, u32 as, int strip)
as_path_prepend2(struct linpool *pool, const struct adata *op, int seq, u32 as)
{
struct adata *np;
const byte *pos = op->data;
......@@ -218,10 +230,7 @@ as_path_prepend2(struct linpool *pool, const struct adata *op, int seq, u32 as,
{
byte *dst = np->data + 2 + BS * np->data[1];
if (strip)
as_path_strip_confed_(dst, pos, len);
else
memcpy(dst, pos, len);
memcpy(dst, pos, len);
}
return np;
......@@ -325,46 +334,49 @@ as_path_merge(struct linpool *pool, struct adata *p1, struct adata *p2)
}
void
as_path_format(const struct adata *path, byte *buf, uint size)
as_path_format(const struct adata *path, byte *bb, uint size)
{
const byte *p = path->data;
const byte *e = p + path->length;
byte *end = buf + size - 16;
int sp = 1;
int l, isset;
buffer buf = { .start = bb, .pos = bb, .end = bb + size }, *b = &buf;
const byte *pos = path->data;
const byte *end = pos + path->length;
const char *ops, *cls;
b->pos[0] = 0;
while (pos < end)
{
uint type = pos[0];
uint len = pos[1];
pos += 2;
while (p < e)
switch (type)
{
if (buf > end)
{
strcpy(buf, " ...");
return;
}
isset = (*p++ == AS_PATH_SET);
l = *p++;
if (isset)
{
if (!sp)
*buf++ = ' ';
*buf++ = '{';
sp = 0;
}
while (l-- && buf <= end)
{
if (!sp)
*buf++ = ' ';
buf += bsprintf(buf, "%u", get_as(p));
p += BS;
sp = 0;
}
if (isset)
{
*buf++ = ' ';
*buf++ = '}';
sp = 0;
}
case AS_PATH_SET: ops = "{"; cls = "}"; break;
case AS_PATH_SEQUENCE: ops = NULL; cls = NULL; break;
case AS_PATH_CONFED_SEQUENCE: ops = "("; cls = ")"; break;
case AS_PATH_CONFED_SET: ops = "({"; cls = "})"; break;
default: bug("Invalid path segment");
}
*buf = 0;
if (ops)
buffer_puts(b, ops);
while (len--)
{
buffer_print(b, len ? "%u " : "%u", get_as(pos));
pos += BS;
}
if (cls)
buffer_puts(b, cls);
if (pos < end)
buffer_puts(b, " ");
}
/* Handle overflow */
if (b->pos == b->end)
strcpy(b->end - 12, "...");
}
int
......@@ -399,66 +411,80 @@ as_path_getlen(const struct adata *path)
int
as_path_get_last(const struct adata *path, u32 *orig_as)
{
const byte *pos = path->data;
const byte *end = pos + path->length;
int found = 0;
u32 res = 0;
const u8 *p = path->data;
const u8 *q = p+path->length;
int len;
u32 val = 0;
while (p<q)
while (pos < end)
{
uint type = pos[0];
uint len = pos[1];
pos += 2;
if (!len)
continue;
switch (type)
{
switch (*p++)
{
case AS_PATH_SET:
if (len = *p++)
{
found = 0;
p += BS * len;
}
break;
case AS_PATH_SEQUENCE:
if (len = *p++)
{
found = 1;
res = get_as(p + BS * (len - 1));
p += BS * len;
}
break;
default: bug("Invalid path segment");
}
case AS_PATH_SET:
case AS_PATH_CONFED_SET:
found = 0;
break;
case AS_PATH_SEQUENCE:
case AS_PATH_CONFED_SEQUENCE:
val = get_as(pos + BS * (len - 1));
found = 1;
break;
default:
bug("Invalid path segment");
}
pos += BS * len;
}
if (found)
*orig_as = res;
*orig_as = val;
return found;
}
u32
as_path_get_last_nonaggregated(const struct adata *path)
{
const u8 *p = path->data;
const u8 *q = p+path->length;
u32 res = 0;
int len;
const byte *pos = path->data;
const byte *end = pos + path->length;
u32 val = 0;
while (p<q)
while (pos < end)
{