Commit 96660260 authored by Ondřej Filip's avatar Ondřej Filip

Merge branch 'int-new' of ssh://gitlab.labs.nic.cz/labs/bird into int-new

parents 44062812 4841804f
Version 2.0.2 (2018-03-xx)
o Source-specific routing support for Linux kernel and Babel
o BGP: New option 'disable after cease'
o Filter: Allow silent filter execution
o Filter: Fixed stack overflow in BGP mask expressions.
o Several bugfixes
Notes:
Syntax prefix:netmask for IPv4 prefixes was dropped. Just use prefix/pxlen.
Version 2.0.1 (2018-01-16)
o Linux MPLS kernel support
o Better handling of channels inherited from templates
......
......@@ -49,6 +49,8 @@ CF_DECLS
struct rtable_config *r;
struct channel_config *cc;
struct f_inst *x;
struct f_dynamic_attr fda;
struct f_static_attr fsa;
struct filter *f;
struct f_tree *e;
struct f_trie *trie;
......@@ -177,10 +179,6 @@ pxlen4:
if ($2 > IP4_MAX_PREFIX_LENGTH) cf_error("Invalid prefix length %u", $2);
$$ = $2;
}
| ':' IP4 {
$$ = ip4_masklen($2);
if ($$ == 255) cf_error("Invalid netmask %I4", $2);
}
;
net_ip4_: IP4 pxlen4
......
This diff is collapsed.
......@@ -293,6 +293,20 @@ routes are:
<item>Route next hops (see below)
</itemize>
<sect1>IPv6 source-specific routes
<label id="ip-sadr-routes">
<p>The IPv6 routes containing both destination and source prefix. They are used
for source-specific routing (SSR), also called source-address dependent routing
(SADR), see <rfc id="8043">. Currently limited mostly to the Babel protocol.
Configuration keyword is <cf/ipv6 sadr/.
<itemize>
<item>(PK) Route destination (IP prefix together with its length)
<item>(PK) Route source (IP prefix together with its length)
<item>Route next hops (see below)
</itemize>
<sect1>VPN IPv4 and IPv6 routes
<label id="vpn-routes">
......@@ -646,9 +660,9 @@ agreement").
restricted to interfaces assigned to the VRF and will use sockets bound
to the VRF. Appropriate VRF interface must exist on OS level. For kernel
protocol, an appropriate table still must be explicitly selected by
<cf/table/ option. Note that the VRF support in BIRD and Linux kernel
(4.11) is still in development and is currently problematic outside of
multihop BGP.
<cf/table/ option. Note that for proper VRF support it is necessary to
use Linux kernel version at least 4.14, older versions have limited VRF
implementation.
<tag><label id="proto-channel"><m/channel name/ [{<m/channel config/}]</tag>
Every channel must be explicitly stated. See the protocol-specific
......@@ -1234,12 +1248,17 @@ foot).
operator <cf/.type/. The type may be:
<cf/NET_IP4/ and <cf/NET_IP6/ prefixes hold an IP prefix. The literals
are written as <cf><m/ipaddress//<m/pxlen/</cf>,
or <cf><m>ipaddress</m>/<m>netmask</m></cf>. There are two special
are written as <cf><m/ipaddress//<m/pxlen/</cf>. There are two special
operators on these: <cf/.ip/ which extracts the IP address from the
pair, and <cf/.len/, which separates prefix length from the pair.
So <cf>1.2.0.0/16.len = 16</cf> is true.
<cf/NET_IP6_SADR/ nettype holds both destination and source IPv6
prefix. The literals are written as <cf><m/ipaddress//<m/pxlen/ from
<m/ipaddress//<m/pxlen/</cf>, where the first part is the destination
prefix and the second art is the source prefix. They support the same
operators as IP prefixes, but just for the destination part.
<cf/NET_VPN4/ and <cf/NET_VPN6/ prefixes hold an IP prefix with VPN
Route Distinguisher (<rfc id="4364">). They support the same special
operators as IP prefixes, and also <cf/.rd/ which extracts the Route
......@@ -1460,6 +1479,7 @@ foot).
lclists, with LCs instead of pairs as arguments.
</descrip>
<sect>Operators
<label id="operators">
......@@ -1652,19 +1672,25 @@ cases desirable.
routes over the same IPv6 transport. For sending and receiving Babel packets,
only a link-local IPv6 address is needed.
<p>BIRD does not implement any Babel extensions, but will coexist with
implementations using extensions (and will just ignore extension messages).
<p>BIRD implements an extension for IPv6 source-specific routing (SSR or SADR),
but must be configured accordingly to use it. SADR-enabled Babel router can
interoperate with non-SADR Babel router, but the later would ignore routes
with specific (non-zero) source prefix.
<sect1>Configuration
<label id="babel-config">
<p>Babel supports no global configuration options apart from those common to all
other protocols, but supports the following per-interface configuration options:
<p>The Babel protocol support both IPv4 and IPv6 channels; both can be
configured simultaneously. It can also be configured with <ref
id="ip-sadr-routes" name="IPv6 SADR"> channel instead of regular IPv6
channel, in such case SADR support is enabled. Babel supports no global
configuration options apart from those common to all other protocols, but
supports the following per-interface configuration options:
<code>
protocol babel [<name>] {
ipv4 { <channel config> };
ipv6 { <channel config> };
ipv6 [sadr] { <channel config> };
interface <interface pattern> {
type <wired|wireless>;
rxcost <number>;
......@@ -1684,8 +1710,8 @@ protocol babel [<name>] {
</code>
<descrip>
<tag><label id="babel-channel">ipv4|ipv6 <m/channel config/</tag>
The supported channels are IPv4 and IPv6.
<tag><label id="babel-channel">ipv4 | ipv6 [sadr] <m/channel config/</tag>
The supported channels are IPv4, IPv6, and IPv6 SADR.
<tag><label id="babel-type">type wired|wireless </tag>
This option specifies the interface type: Wired or wireless. On wired
......@@ -2119,22 +2145,24 @@ to set routing policy and all the other parameters differently for each neighbor
using the following configuration parameters:
<descrip>
<tag><label id="bgp-local">local [<m/ip/] as <m/number/</tag>
<tag><label id="bgp-local">local [<m/ip/] [port <m/number/] [as <m/number/]</tag>
Define which AS we are part of. (Note that contrary to other IP routers,
BIRD is able to act as a router located in multiple AS'es simultaneously,
but in such cases you need to tweak the BGP paths manually in the filters
to get consistent behavior.) Optional <cf/ip/ argument specifies a source
address, equivalent to the <cf/source address/ option (see below). This
parameter is mandatory.
address, equivalent to the <cf/source address/ option (see below).
Optional <cf/port/ argument specifies the local BGP port instead of
standard port 179. The parameter may be used multiple times with
different sub-options (e.g., both <cf/local 10.0.0.1 as 65000;/ and
<cf/local 10.0.0.1; local as 65000;/ are valid). This parameter is
mandatory.
<tag><label id="bgp-neighbor">neighbor [<m/ip/] [port <m/number/] [as <m/number/]</tag>
Define neighboring router this instance will be talking to and what AS
it is located in. In case the neighbor is in the same AS as we are, we
automatically switch to iBGP. Optionally, the remote port may also be
specified. The parameter may be used multiple times with different
sub-options (e.g., both <cf/neighbor 10.0.0.1 as 65000;/ and
<cf/neighbor 10.0.0.1; neighbor as 65000;/ are valid). This parameter is
mandatory.
specified. Like <cf/local/ parameter, this parameter may also be used
multiple times with different sub-options. This parameter is mandatory.
<tag><label id="bgp-iface">interface <m/string/</tag>
Define interface we should use for link-local BGP IPv6 sessions.
......@@ -2744,16 +2772,17 @@ protocol device {
<p>The Direct protocol is a simple generator of device routes for all the
directly connected networks according to the list of interfaces provided by the
kernel via the Device protocol. The Direct protocol supports both IPv4 and IPv6
channels.
channels; both can be configured simultaneously. It can also be configured with
<ref id="ip-sadr-routes" name="IPv6 SADR"> channel instead of regular IPv6
channel in order to be used together with SADR-enabled Babel protocol.
<p>The question is whether it is a good idea to have such device routes in BIRD
routing table. OS kernel usually handles device routes for directly connected
networks by itself so we don't need (and don't want) to export these routes to
the kernel protocol. OSPF protocol creates device routes for its interfaces
itself and BGP protocol is usually used for exporting aggregate routes. Although
there are some use cases that use the direct protocol (like abusing eBGP as an
IGP routing protocol), in most cases it is not needed to have these device
routes in BIRD routing table and to use the direct protocol.
itself and BGP protocol is usually used for exporting aggregate routes. But the
Direct protocol is necessary for distance-vector protocols like RIP or Babel to
announce local networks.
<p>There is one notable case when you definitely want to use the direct protocol
-- running BIRD on BSD systems. Having high priority device routes for directly
......@@ -2828,8 +2857,10 @@ kernel protocols to the same routing table and changing route destination
(gateway) in an export filter of a kernel protocol does not work. Both
limitations can be overcome using another routing table and the pipe protocol.
<p>The Kernel protocol supports both IPv4 and IPv6 channels; only one of them
can be configured in each protocol instance.
<p>The Kernel protocol supports both IPv4 and IPv6 channels; only one channel
can be configured in each protocol instance. On Linux, it also supports <ref
id="ip-sadr-routes" name="IPv6 SADR"> and <ref id="mpls-routes" name="MPLS">
channels.
<sect1>Configuration
<label id="krt-config">
......@@ -4280,6 +4311,7 @@ protocol rip {
<sect>RPKI
<label id="rpki">
<sect1>Introduction
......
This diff is collapsed.
......@@ -2,6 +2,7 @@
* Filters: utility functions
*
* Copyright 1998 Pavel Machek <pavel@ucw.cz>
* 2017 Jan Maria Matejka <mq@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
......@@ -13,43 +14,48 @@
#define P(a,b) ((a<<8) | b)
struct f_inst *
f_new_inst(void)
f_new_inst(enum f_instruction_code fi_code)
{
struct f_inst * ret;
ret = cfg_alloc(sizeof(struct f_inst));
ret->code = ret->aux = 0;
ret->arg1 = ret->arg2 = ret->next = NULL;
ret = cfg_allocz(sizeof(struct f_inst));
ret->fi_code = fi_code;
ret->lineno = ifs->lino;
return ret;
}
struct f_inst *
f_new_dynamic_attr(int type, int f_type, int code)
f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da)
{
/* FIXME: Remove the f_type parameter? */
struct f_inst *f = f_new_inst();
f->aux = (f_type << 8) | type;
f->a2.i = code;
return f;
struct f_inst *ret = f_new_inst(fi_code);
ret->aux = (da.f_type << 8) | da.type;
ret->a2.i = da.ea_code;
return ret;
}
struct f_inst *
f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa)
{
struct f_inst *ret = f_new_inst(fi_code);
ret->aux = sa.f_type;
ret->a2.i = sa.sa_code;
ret->a1.i = sa.readonly;
return ret;
}
/*
* Generate set_dynamic( operation( get_dynamic(), argument ) )
*/
struct f_inst *
f_generate_complex(int operation, int operation_aux, struct f_inst *dyn, struct f_inst *argument)
f_generate_complex(int operation, int operation_aux, struct f_dynamic_attr da, struct f_inst *argument)
{
struct f_inst *set_dyn = f_new_inst(),
*oper = f_new_inst(),
*get_dyn = dyn;
struct f_inst *set_dyn = f_new_inst_da(FI_EA_SET, da),
*oper = f_new_inst(operation),
*get_dyn = f_new_inst_da(FI_EA_GET, da);
*set_dyn = *get_dyn;
get_dyn->code = P('e','a');
oper->code = operation;
oper->aux = operation_aux;
oper->a1.p = get_dyn;
oper->a2.p = argument;
set_dyn->code = P('e','S');
set_dyn->a1.p = oper;
return set_dyn;
}
......@@ -58,7 +64,7 @@ struct f_inst *
f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn)
{
struct f_inst_roa_check *ret = cfg_allocz(sizeof(struct f_inst_roa_check));
ret->i.code = P('R','C');
ret->i.fi_code = FI_ROA_CHECK;
ret->i.lineno = ifs->lino;
ret->i.arg1 = prefix;
ret->i.arg2 = asn;
......
This diff is collapsed.
......@@ -14,9 +14,74 @@
#include "nest/route.h"
#include "nest/attrs.h"
/* Filter instruction types */
#define FI__TWOCHAR(a,b) ((a<<8) | b)
#define FI__LIST \
F(FI_ADD, 0, '+') \
F(FI_SUBTRACT, 0, '-') \
F(FI_MULTIPLY, 0, '*') \
F(FI_DIVIDE, 0, '/') \
F(FI_AND, 0, '&') \
F(FI_OR, 0, '|') \
F(FI_PAIR_CONSTRUCT, 'm', 'p') \
F(FI_EC_CONSTRUCT, 'm', 'c') \
F(FI_LC_CONSTRUCT, 'm', 'l') \
F(FI_PATHMASK_CONSTRUCT, 'm', 'P') \
F(FI_NEQ, '!', '=') \
F(FI_EQ, '=', '=') \
F(FI_LT, 0, '<') \
F(FI_LTE, '<', '=') \
F(FI_NOT, 0, '!') \
F(FI_MATCH, 0, '~') \
F(FI_NOT_MATCH, '!', '~') \
F(FI_DEFINED, 'd', 'e') \
F(FI_TYPE, 0, 'T') \
F(FI_IS_V4, 'I', 'i') \
F(FI_SET, 0, 's') \
F(FI_CONSTANT, 0, 'c') \
F(FI_VARIABLE, 0, 'V') \
F(FI_CONSTANT_INDIRECT, 0, 'C') \
F(FI_PRINT, 0, 'p') \
F(FI_CONDITION, 0, '?') \
F(FI_NOP, 0, '0') \
F(FI_PRINT_AND_DIE, 'p', ',') \
F(FI_RTA_GET, 0, 'a') \
F(FI_RTA_SET, 'a', 'S') \
F(FI_EA_GET, 'e', 'a') \
F(FI_EA_SET, 'e', 'S') \
F(FI_PREF_GET, 0, 'P') \
F(FI_PREF_SET, 'P', 'S') \
F(FI_LENGTH, 0, 'L') \
F(FI_ROA_MAXLEN, 'R', 'M') \
F(FI_ROA_ASN, 'R', 'A') \
F(FI_IP, 'c', 'p') \
F(FI_ROUTE_DISTINGUISHER, 'R', 'D') \
F(FI_AS_PATH_FIRST, 'a', 'f') \
F(FI_AS_PATH_LAST, 'a', 'l') \
F(FI_AS_PATH_LAST_NAG, 'a', 'L') \
F(FI_RETURN, 0, 'r') \
F(FI_CALL, 'c', 'a') \
F(FI_CLEAR_LOCAL_VARS, 'c', 'V') \
F(FI_SWITCH, 'S', 'W') \
F(FI_IP_MASK, 'i', 'M') \
F(FI_EMPTY, 0, 'E') \
F(FI_PATH_PREPEND, 'A', 'p') \
F(FI_CLIST_ADD_DEL, 'C', 'a') \
F(FI_ROA_CHECK, 'R', 'C') \
F(FI_FORMAT, 0, 'F') \
F(FI_ASSERT, 'a', 's')
enum f_instruction_code {
#define F(c,a,b) \
c = FI__TWOCHAR(a,b),
FI__LIST
#undef F
} PACKED;
struct f_inst { /* Instruction */
struct f_inst *next; /* Structure is 16 bytes, anyway */
u16 code; /* Instruction code, see the interpret() function and P() macro */
enum f_instruction_code fi_code;
u16 aux; /* Extension to instruction code, T_*, EA_*, EAF_* */
union {
uint i;
......@@ -70,15 +135,32 @@ struct f_val {
} val;
};
struct f_dynamic_attr {
int type;
int f_type;
int ea_code;
};
struct f_static_attr {
int f_type;
int sa_code;
int readonly;
};
struct filter {
char *name;
struct f_inst *root;
};
struct f_inst *f_new_inst(void);
struct f_inst *f_new_dynamic_attr(int type, int f_type, int code); /* Type as core knows it, type as filters know it, and code of dynamic attribute */
struct f_inst *f_new_inst(enum f_instruction_code fi_code);
struct f_inst *f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da);
struct f_inst *f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa);
static inline struct f_dynamic_attr f_new_dynamic_attr(int type, int f_type, int code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
{ return (struct f_dynamic_attr) { .type = type, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */
static inline struct f_static_attr f_new_static_attr(int f_type, int code, int readonly)
{ return (struct f_static_attr) { .f_type = f_type, .sa_code = code, .readonly = readonly }; }
struct f_tree *f_new_tree(void);
struct f_inst *f_generate_complex(int operation, int operation_aux, struct f_inst *dyn, struct f_inst *argument);
struct f_inst *f_generate_complex(int operation, int operation_aux, struct f_dynamic_attr da, struct f_inst *argument);
struct f_inst *f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn);
......@@ -100,7 +182,6 @@ int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, s
struct f_val f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool);
struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool);
uint f_eval_int(struct f_inst *expr);
u32 f_eval_asn(struct f_inst *expr);
char *filter_name(struct filter *filter);
int filter_same(struct filter *new, struct filter *old);
......
......@@ -55,29 +55,28 @@ protocol static {
rip_metric = rip_metric + 5;
print rip_metric;
#
# TODO: uncomment this part after finishing BGP integration version
#
# bgp_community = -empty-;
# print "hi";
# bgp_community = add(bgp_community, (1,2));
# print "hello";
# bgp_community = add(bgp_community, (2,3));
# bgp_community.add((4,5));
# print "community = ", bgp_community;
# bgp_community.delete((2,3));
# print "community = ", bgp_community;
# bgp_community.empty;
# print "community = ", bgp_community;
# print "done";
bgp_community = -empty-;
print "hi";
bgp_community = add(bgp_community, (1,2));
print "hello";
bgp_community = add(bgp_community, (2,3));
bgp_community.add((4,5));
print "community = ", bgp_community;
bgp_community.delete((2,3));
print "community = ", bgp_community;
bgp_community.empty;
print "community = ", bgp_community;
print "done";
accept;
};
};
route 0.0.0.0/0 via 195.113.31.113;
route 62.168.0.0/25 reject;
route 1.2.3.4/32 via 195.113.31.124;
route 10.0.0.0/8 reject;
route 10.1.1.0:255.255.255.0 via 62.168.0.3;
route 10.1.2.0:255.255.255.0 via 62.168.0.3;
route 10.1.3.0:255.255.255.0 via 62.168.0.4;
route 10.1.1.0/24 via 62.168.0.3;
route 10.1.2.0/24 via 62.168.0.3;
route 10.1.3.0/24 via 62.168.0.4;
route 10.2.0.0/24 via "arc0";
}
Summary: BIRD Internet Routing Daemon
Name: bird
Version: 2.0.1
Version: 2.0.2
Release: 1
Copyright: GPL
Group: Networking/Daemons
......
......@@ -805,8 +805,7 @@ as_path_match(const struct adata *path, struct f_path_mask *mask)
val2 = val = mask->val;
goto step;
case PM_ASN_EXPR:
val2 = val = f_eval_asn((struct f_inst *) mask->val);
goto step;
ASSERT(0);
case PM_ASN_RANGE:
val = mask->val;
val2 = mask->val2;
......
......@@ -31,6 +31,7 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
struct rt_dev_proto *p = (void *) P;
struct rt_dev_config *cf = (void *) P->cf;
struct channel *c;
net_addr *net = &ad->prefix;
if (!EMPTY_LIST(cf->iface_list) &&
!iface_patt_find(&cf->iface_list, ad->iface, ad))
......@@ -53,13 +54,20 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
if (!c)
return;
/* For IPv6 SADR, replace regular prefix with SADR prefix */
if (c->net_type == NET_IP6_SADR)
{
net = alloca(sizeof(net_addr_ip6_sadr));
net_fill_ip6_sadr(net, net6_prefix(&ad->prefix), net6_pxlen(&ad->prefix), IP6_NONE, 0);
}
if (flags & IF_CHANGE_DOWN)
{
DBG("dev_if_notify: %s:%I going down\n", ad->iface->name, ad->ip);
/* Use iface ID as local source ID */
struct rte_src *src = rt_get_source(P, ad->iface->index);
rte_update2(c, &ad->prefix, NULL, src);
rte_update2(c, net, NULL, src);
}
else if (flags & IF_CHANGE_UP)
{
......@@ -85,7 +93,7 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
a = rta_lookup(&a0);
e = rte_get_temp(a);
e->pflags = 0;
rte_update2(c, &ad->prefix, e, src);
rte_update2(c, net, e, src);
}
}
......@@ -107,16 +115,32 @@ dev_if_notify(struct proto *p, uint c, struct iface *iface)
}
}
static void
dev_postconfig(struct proto_config *CF)
{
struct rt_dev_config *cf = (void *) CF;
struct channel_config *ip4, *ip6, *ip6_sadr;
ip4 = proto_cf_find_channel(CF, NET_IP4);
ip6 = proto_cf_find_channel(CF, NET_IP6);
ip6_sadr = proto_cf_find_channel(CF, NET_IP6_SADR);
if (ip6 && ip6_sadr)
cf_error("Both ipv6 and ipv6-sadr channels");
cf->ip4_channel = ip4;
cf->ip6_channel = ip6 ?: ip6_sadr;
}
static struct proto *
dev_init(struct proto_config *CF)
{
struct proto *P = proto_new(CF);
struct rt_dev_proto *p = (void *) P;
// struct rt_dev_config *cf = (void *) CF;
struct rt_dev_config *cf = (void *) 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));
proto_configure_channel(P, &p->ip4_channel, cf->ip4_channel);
proto_configure_channel(P, &p->ip6_channel, cf->ip6_channel);
P->if_notify = dev_if_notify;
P->ifa_notify = dev_ifa_notify;
......@@ -136,8 +160,8 @@ dev_reconfigure(struct proto *P, struct proto_config *CF)
return 0;
return
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));
proto_configure_channel(P, &p->ip4_channel, n->ip4_channel) &&
proto_configure_channel(P, &p->ip6_channel, n->ip6_channel);
return 1;
}
......@@ -162,9 +186,10 @@ struct protocol proto_device = {
.name = "Direct",
.template = "direct%d",
.preference = DEF_PREF_DIRECT,
.channel_mask = NB_IP,
.channel_mask = NB_IP | NB_IP6_SADR,
.proto_size = sizeof(struct rt_dev_proto),
.config_size = sizeof(struct rt_dev_config),
.postconfig = dev_postconfig,
.init = dev_init,
.reconfigure = dev_reconfigure,
.copy_config = dev_copy_config
......
......@@ -13,6 +13,9 @@ struct rt_dev_config {
struct proto_config c;
list iface_list; /* list of struct iface_patt */
int check_link;
struct channel_config *ip4_channel;
struct channel_config *ip6_channel;
};
struct rt_dev_proto {
......
......@@ -2076,6 +2076,13 @@ rt_unlock_table(rtable *r)
}
}
static struct rtable_config *
rt_find_table_config(struct config *cf, char *name)
{
struct symbol *sym = cf_find_symbol(cf, name);
return (sym && (sym->class == SYM_TABLE)) ? sym->def : NULL;
}
/**
* rt_commit - commit new routing table configuration
* @new: new configuration
......@@ -2101,11 +2108,10 @@ rt_commit(struct config *new, struct config *old)
rtable *ot = o->table;
if (!ot->deleted)
{
struct symbol *sym = cf_find_symbol(new, o->name);
if (sym && sym->class == SYM_TABLE && !new->shutdown)
r = rt_find_table_config(new, o->name);
if (r && (r->addr_type == o->addr_type) && !new->shutdown)
{
DBG("\t%s: same\n", o->name);
r = sym->def;
r->table = ot;
ot->name = r->name;
ot->config = r;
......
......@@ -22,9 +22,10 @@ CF_DEFINES
CF_DECLS
CF_KEYWORDS(BABEL, METRIC, RXCOST, HELLO, UPDATE, INTERVAL, PORT, WIRED,
WIRELESS, RX, TX, BUFFER, LENGTH, CHECK, LINK, BABEL_METRIC, NEXT, HOP,
IPV4, IPV6)
CF_KEYWORDS(BABEL, INTERFACE, METRIC, RXCOST, HELLO, UPDATE, INTERVAL, PORT,
TYPE, WIRED, WIRELESS, RX, TX, BUFFER, PRIORITY, LENGTH, CHECK, LINK,
NEXT, HOP, IPV4, IPV6, BABEL_METRIC, SHOW, INTERFACES, NEIGHBORS,
ENTRIES)
CF_GRAMMAR
......
......@@ -13,7 +13,7 @@
#ifdef GIT_LABEL
#define BIRD_VERSION XSTR1(GIT_LABEL)
#else
#define BIRD_VERSION "2.0.1"
#define BIRD_VERSION "2.0.2"
#endif
/* Include parameters determined by configure script */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment