summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.in15
-rw-r--r--doc/bird.sgml37
-rw-r--r--proto/bgp/attrs.c12
-rw-r--r--proto/bgp/bgp.h1
-rw-r--r--proto/bgp/config.Y3
-rw-r--r--sysdep/unix/main.c67
-rw-r--r--tools/Makefile.in1
7 files changed, 121 insertions, 15 deletions
diff --git a/configure.in b/configure.in
index 230b57b4..46a6ecd9 100644
--- a/configure.in
+++ b/configure.in
@@ -13,6 +13,7 @@ AC_ARG_ENABLE(ipv6,[ --enable-ipv6 enable building of IPv6 version (d
AC_ARG_WITH(sysconfig,[ --with-sysconfig=FILE use specified BIRD system configuration file])
AC_ARG_WITH(protocols,[ --with-protocols=LIST include specified routing protocols (default: all)],,[with_protocols="all"])
AC_ARG_WITH(sysinclude,[ --with-sysinclude=PATH search for system includes on specified place])
+AC_ARG_WITH(iproutedir,[ --with-iproutedir=PATH path to iproute2 config files (default: /etc/iproute2)],[given_iproutedir="yes"])
AC_ARG_VAR([FLEX], [location of the Flex program])
AC_ARG_VAR([BISON], [location of the Bison program])
AC_ARG_VAR([M4], [location of the M4 program])
@@ -105,12 +106,14 @@ elif test -f sysconfig.h ; then
else
case "$ip:$host_os" in
ipv4:linux*) BIRD_CHECK_LINUX_VERSION
+ default_iproutedir="/etc/iproute2"
case $bird_cv_sys_linux_version in
1.*|2.0.*) sysdesc=linux-20 ;;
*) sysdesc=linux-22 ;;
esac
;;
ipv6:linux*) BIRD_CHECK_LINUX_VERSION
+ default_iproutedir="/etc/iproute2"
case $bird_cv_sys_linux_version in
1.*|2.0.*) AC_MSG_ERROR([This version of Linux doesn't support IPv6.]) ;;
*) sysdesc=linux-v6 ;;
@@ -154,6 +157,15 @@ sysdep_dirs="`sed <$sysdesc '/^Link: /!d;s/^Link: \(.*\)$/\1/' | tr '\012' ' '`
AC_MSG_RESULT($sysdep_dirs)
AC_SUBST(sysdep_dirs)
+if test "$with_iproutedir" = no ; then with_iproutedir= ; fi
+
+if test -n "$given_iproutedir"
+then iproutedir=$with_iproutedir
+else iproutedir=$default_iproutedir
+fi
+
+AC_SUBST(iproutedir)
+
AC_MSG_CHECKING([protocols])
protocols=`echo "$with_protocols" | sed 's/,/ /g'`
if test "$protocols" = no ; then protocols= ; fi
@@ -234,11 +246,14 @@ $srcdir/tools/mergedirs $srcdir $srcdir_rel $objdir $sysdep_dirs]],
AC_CONFIG_FILES($makefiles)
AC_OUTPUT
+rm -f $objdir/sysdep/paths.h
+
cat >&AC_FD_MSG <<EOF
BIRD was configured with the following options:
Source directory: $srcdir
Object directory: $objdir
+ Iproute2 directory: $iproutedir
System configuration: $sysdesc
Debugging: $enable_debug
Routing protocols: $protocols
diff --git a/doc/bird.sgml b/doc/bird.sgml
index 86f4c507..31b2c03f 100644
--- a/doc/bird.sgml
+++ b/doc/bird.sgml
@@ -266,8 +266,10 @@ protocol rip {
about configuring protocols in their own chapters. You can run more than one instance of
most protocols (like RIP or BGP). By default, no instances are configured.
- <tag>define <m/constant/ = (<m/expression/)|<m/number/|<m/IP address/</tag> Define a constant. You can use it later in every place
- you could use a simple integer or an IP address.
+ <tag>define <m/constant/ = (<m/expression/)|<m/number/|<m/IP address/</tag>
+ Define a constant. You can use it later in every place you could use a simple integer or an IP address.
+ Besides, there are some predefined numeric constants based on /etc/iproute2/rt_* files.
+ A list of defined constants can be seen (together with other symbols) using 'show symbols' command.
<tag>router id <m/IPv4 address/</tag> Set BIRD's router ID. It's a world-wide unique identification of your router, usually one of router's IPv4 addresses. Default: in IPv4 version, the lowest IP address of a non-loopback interface. In IPv6 version, this option is mandatory.
@@ -1121,7 +1123,7 @@ for each neighbor using the following configuration parameters:
BIRD does not implement obsoleted RFC 1863, but uses ad-hoc implementation,
which behaves like plain EBGP but reduces modifications to advertised route
attributes to be transparent (for example does not prepend its AS number to
- AS PATH attribute and keep MED attribute). Default: disabled.
+ AS PATH attribute and keeps MED attribute). Default: disabled.
<tag>enable route refresh <m/switch/</tag> When BGP speaker
changes its import filter, it has to re-examine all routes
@@ -1205,6 +1207,15 @@ for each neighbor using the following configuration parameters:
<tag>path metric <m/switch/</tag> Enable comparison of path lengths
when deciding which BGP route is the best one. Default: on.
+ <tag>med metric <m/switch/</tag> Enable comparison of MED
+ attributes (during best route selection) even between routes
+ received from different ASes. This may be useful if all MED
+ attributes contain some consistent metric, perhaps enforced in
+ import filters of AS boundary routers. If this option is
+ disabled, MED attributes are compared only if routes are
+ received from the same AS (which is the standard behavior).
+ Default: off.
+
<tag>igp metric <m/switch/</tag> Enable comparison of internal
distances to boundary routers during best route selection. Default: on.
@@ -1233,21 +1244,21 @@ with `<tt/O/') are optional.
<descrip>
<tag>bgppath <cf/bgp_path/</tag> Sequence of AS numbers describing the AS path
- the packet will travel through when forwarded according to the particular route. In case of
- internal BGP it doesn't contain the number of the local AS.
+ the packet will travel through when forwarded according to the particular route.
+ In case of internal BGP it doesn't contain the number of the local AS.
<tag>int <cf/bgp_local_pref/ [I]</tag> Local preference value used for
selection among multiple BGP routes (see the selection rules above). It's
used as an additional metric which is propagated through the whole local AS.
<tag>int <cf/bgp_med/ [O]</tag> The Multiple Exit Discriminator of the route
- is an optional attribute which is used on on external (inter-AS) links to
+ is an optional attribute which is used on external (inter-AS) links to
convey to an adjacent AS the optimal entry point into the local AS.
- The received attribute may be also propagated over internal BGP links
- (and this is default behavior). The attribute value is zeroed when a route
- is exported from a routing table to a BGP instance to ensure that the attribute
- received from a neighboring AS is not propagated to other neighboring ASes.
- A new value might be set in the export filter of a BGP instance.
+ The received attribute is also propagated over internal BGP links.
+ The attribute value is zeroed when a route is exported to an external BGP
+ instance to ensure that the attribute received from a neighboring AS is
+ not propagated to other neighboring ASes. A new value might be set in
+ the export filter of an external BGP instance.
See RFC 4451<htmlurl url="ftp://ftp.rfc-editor.org/in-notes/rfc4451.txt">
for further discussion of BGP MED attribute.
@@ -1281,11 +1292,11 @@ with `<tt/O/') are optional.
its own routing policy, it also has a complete freedom about which community
attributes it defines and what will their semantics be.
- <tag>quad <cf/bgp_originator_id/ [O]</tag> This attribute is created by the
+ <tag>quad <cf/bgp_originator_id/ [I, O]</tag> This attribute is created by the
route reflector when reflecting the route and contains the router ID of the
originator of the route in the local AS.
- <tag>clist <cf/bgp_cluster_list/ [O]</tag> This attribute contains a list
+ <tag>clist <cf/bgp_cluster_list/ [I, O]</tag> This attribute contains a list
of cluster IDs of route reflectors. Each route reflector prepends its
cluster ID when reflecting the route.
</descrip>
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index e1a3671a..95eee9aa 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -1118,7 +1118,17 @@ bgp_rte_better(rte *new, rte *old)
return 0;
/* RFC 4271 9.1.2.2. c) Compare MED's */
- if (bgp_get_neighbor(new) == bgp_get_neighbor(old))
+ /* This is noncompliant. Proper RFC 4271 path selection cannot be
+ * interpreted as finding the best path in some ordering.
+ * Therefore, it cannot be implemented in BIRD without some ugly
+ * hacks. This is just an approximation, which in specific
+ * situations may lead to persistent routing loops, because it is
+ * nondeterministic - it depends on the order in which routes
+ * appeared. But it is also the same behavior as used by default in
+ * Cisco routers, so it is probably not a big issue.
+ */
+ if (new_bgp->cf->med_metric || old_bgp->cf->med_metric ||
+ (bgp_get_neighbor(new) == bgp_get_neighbor(old)))
{
x = ea_find(new->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
y = ea_find(old->attrs->eattrs, EA_CODE(EAP_BGP, BA_MULTI_EXIT_DISC));
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index b06f20a0..097faa6a 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -25,6 +25,7 @@ struct bgp_config {
int missing_lladdr; /* What we will do when we don' know link-local addr, see MLL_* */
int gw_mode; /* How we compute route gateway from next_hop attr, see GW_* */
int compare_path_lengths; /* Use path lengths when selecting best route */
+ int med_metric; /* Compare MULTI_EXIT_DISC even between routes from differen ASes */
int igp_metric; /* Use IGP metrics when selecting best route */
int prefer_older; /* Prefer older routes according to RFC 5004 */
u32 default_local_pref; /* Default value for LOCAL_PREF attribute */
diff --git a/proto/bgp/config.Y b/proto/bgp/config.Y
index e932a7f6..93f832aa 100644
--- a/proto/bgp/config.Y
+++ b/proto/bgp/config.Y
@@ -25,7 +25,7 @@ CF_KEYWORDS(BGP, LOCAL, NEIGHBOR, AS, HOLD, TIME, CONNECT, RETRY,
ADVERTISE, IPV4, CAPABILITIES, LIMIT, PASSIVE, PREFER, OLDER,
MISSING, LLADDR, DROP, IGNORE, ROUTE, REFRESH, INTERPRET,
COMMUNITIES, BGP_ORIGINATOR_ID, BGP_CLUSTER_LIST, IGP, TABLE,
- GATEWAY, DIRECT, RECURSIVE)
+ GATEWAY, DIRECT, RECURSIVE, MED)
CF_GRAMMAR
@@ -79,6 +79,7 @@ bgp_proto:
| bgp_proto GATEWAY DIRECT ';' { BGP_CFG->gw_mode = GW_DIRECT; }
| bgp_proto GATEWAY RECURSIVE ';' { BGP_CFG->gw_mode = GW_RECURSIVE; }
| bgp_proto PATH METRIC bool ';' { BGP_CFG->compare_path_lengths = $4; }
+ | bgp_proto MED METRIC bool ';' { BGP_CFG->med_metric = $4; }
| bgp_proto IGP METRIC bool ';' { BGP_CFG->igp_metric = $4; }
| bgp_proto PREFER OLDER bool ';' { BGP_CFG->prefer_older = $4; }
| bgp_proto DEFAULT BGP_MED expr ';' { BGP_CFG->default_med = $4; }
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index 732c9169..fd921ace 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -62,6 +62,66 @@ async_dump(void)
* Reading the Configuration
*/
+#ifdef PATH_IPROUTE_DIR
+
+static inline void
+add_num_const(char *name, int val)
+{
+ struct symbol *s = cf_find_symbol(name);
+ s->class = SYM_NUMBER;
+ s->def = NULL;
+ s->aux = val;
+}
+
+/* the code of read_iproute_table() is based on
+ rtnl_tab_initialize() from iproute2 package */
+static void
+read_iproute_table(char *file, char *prefix, int max)
+{
+ char buf[512], namebuf[512];
+ char *name;
+ int val;
+ FILE *fp;
+
+ strcpy(namebuf, prefix);
+ name = namebuf + strlen(prefix);
+
+ fp = fopen(file, "r");
+ if (!fp)
+ return;
+
+ while (fgets(buf, sizeof(buf), fp))
+ {
+ char *p = buf;
+
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ if (*p == '#' || *p == '\n' || *p == 0)
+ continue;
+
+ if (sscanf(p, "0x%x %s\n", &val, name) != 2 &&
+ sscanf(p, "0x%x %s #", &val, name) != 2 &&
+ sscanf(p, "%d %s\n", &val, name) != 2 &&
+ sscanf(p, "%d %s #", &val, name) != 2)
+ continue;
+
+ if (val < 0 || val > max)
+ continue;
+
+ for(p = name; *p; p++)
+ if ((*p < 'a' || *p > 'z') && (*p < '0' || *p > '9') && (*p != '_'))
+ *p = '_';
+
+ add_num_const(namebuf, val);
+ }
+
+ fclose(fp);
+}
+
+#endif // PATH_IPROUTE_DIR
+
+
static int conf_fd;
static char *config_name = PATH_CONFIG;
@@ -78,6 +138,13 @@ void
sysdep_preconfig(struct config *c)
{
init_list(&c->logfiles);
+
+#ifdef PATH_IPROUTE_DIR
+ // read_iproute_table(PATH_IPROUTE_DIR "/rt_protos", "ipp_", 256);
+ read_iproute_table(PATH_IPROUTE_DIR "/rt_realms", "ipr_", 256);
+ read_iproute_table(PATH_IPROUTE_DIR "/rt_scopes", "ips_", 256);
+ read_iproute_table(PATH_IPROUTE_DIR "/rt_tables", "ipt_", 256);
+#endif
}
int
diff --git a/tools/Makefile.in b/tools/Makefile.in
index 99ae2251..556eba5f 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -50,6 +50,7 @@ sysdep/paths.h:
echo >sysdep/paths.h "/* Generated by Makefile, don't edit manually! */"
echo >>sysdep/paths.h "#define PATH_CONFIG_DIR \"$(sysconfdir)\""
echo >>sysdep/paths.h "#define PATH_CONTROL_SOCKET_DIR \"$(localstatedir)/run\""
+ if test -n "@iproutedir@" ; then echo >>sysdep/paths.h "#define PATH_IPROUTE_DIR \"@iproutedir@\"" ; fi
tags:
cd $(srcdir) ; etags -lc `find $(static-dirs) $(addprefix $(objdir)/,$(dynamic-dirs)) $(client-dirs) -name *.[chY]`